Довольно часто нам нужно имитировать весь модуль, потому что нецелесообразно, чтобы ваш тестовый бегун (например, Jest) использовал реальный модуль. Например, модуль может нуждаться в транспиляции, что может быть нецелесообразно (много настроек или настроек).

Давайте вручную создадим макет нашего модуля в папке __mocks__. Здорово!

// __mocks__/@my-org/my-module.js
module.exports = {
  foo: 'bar'
};

Теперь код, который использует foo, будет использовать макет 'bar' в тестах.

import { foo } from '@my-org/my-module'; // 'bar'

Но есть проблема, когда мы это делаем. Мы не получаем хороших ошибок в тестах, когда к модулю плохо обращаются.

Проблема: Что делать, если осуществляется доступ к несуществующему свойству?

Обычно eslint может отловить плохой доступ к модулю (см. правило no-unresolved). Но, по крайней мере, насколько мне известно (поправьте меня, если я ошибаюсь!), eslint не может идентифицировать неверный доступ к фиктивному модулю.

Это может быть проблемой, потому что тесты могут давать непонятные сбои, когда мы неправильно обращаемся к нашему модулю.

import { Bogus } from '@my-org/my-module'; // undefined

В тесте компонента React вы можете увидеть:

import { Bogus } from '@my-org/my-module'; // undefined
...
render() {
  return <Bogus />
}
...
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Это отстой, ошибка сообщает нам, что не так, но не объясняет, почему. Это потому, что «Поддельный» не определен.

Решение

Что, если бы мы издевались над нашим модулем по-другому, чтобы он выдавал ошибку при плохом доступе?

// __mocks__/@my-org/my-module
const proxy = new Proxy({}, {
  get: (obj, property) => {
    if (obj.hasOwnProperty(property)) {
      return obj[property];
    }
    throw new Error(
      `ERROR: You're trying to access a non-existent ${property} in @my-org/my-module`
    );
  }
});
proxy.foo = 'bar';
module.exports = proxy;

Затем это должно взорваться в тестах, как и ожидалось:

import { Bogus } from '@my-org/my-module'; // Error

Сообщение об ошибке намного яснее в неудачном тесте:

Error: Uncaught [Error: ERROR: You're trying to access a non-existent ${property} in @my-org/my-module]

Отлично! Если вы хотите избавить себя от часов головокружения, обязательно используйте функцию ES6 Proxy для имитации ваших модулей. Удачного кодирования!