Повторный импорт модулей между тестами мокко - PullRequest
0 голосов
/ 24 апреля 2018

В моем экспресс-приложении node / typcript я храню настройки конфигурации в файле settings.json, который загружается и экспортируется как объект config.ts. Каждый модуль, который использует настройки конфигурации, импортирует модуль следующим образом:

import Config from './config';

config.ts выглядит так (упрощенно для этого примера):

class Config {
  public static get(): any {
    const settings = require('settings.json');
    return settings;
  }
}

export default Config.get();

Все это прекрасно работает, когда приложение работает. Однако у меня есть проблемы с моими тестами мокко. В некоторых тестах я хочу изменить настройки конфигурации перед запуском функций приложения (например, Config.someSetting = 'someValue'), а затем сбросить настройки конфигурации до значений по умолчанию перед запуском следующего теста.

Я знаю, что могу вручную сбросить каждое измененное значение конфигурации до значения по умолчанию, но в идеале я хотел бы «повторно импортировать» модуль config.ts, который сбросит все параметры конфигурации до их значений по умолчанию. Мой вопрос: каков наилучший способ сделать это?

Я попытался использовать decache и добавить следующее к afterEach:

decache('./config');

и хотя я вижу, что config.ts больше не находится в кеше требуемых данных, объект Config все еще существует с его текущими значениями для всех последующих тестов (config.ts не "повторно импортируется").

Что я делаю не так?

1 Ответ

0 голосов
/ 24 апреля 2018

Пакеты с кэшированием, такие как decache, должны работать в этом случае, если require('settings.json') переоценивается после decache('settings.json'), то есть вызывается Config.get().

Поскольку это settings.json объект модуля, который являетсямодифицированный, он должен быть восстановлен.decache должен напрямую влиять на пакет, который должен быть удален из кэша, то есть settings.json.Если Config.get() не вызывается более одного раза, ./config' и каждый импортирующий его модуль также должны быть кэшированы.Это делает использование decache неразумным в этом случае.

Проблема здесь в том, что модуль конфигурации не подходит для тестирования.Только статические классы являются антипаттернами.Если Config не экспортируется, как показывает код, это также является антипаттерном, поскольку он обеспечивает абстракцию, которую нельзя использовать более одного раза, при экспорте модуля.

Для улучшения ситуации, модуль конфигурацииследует реорганизовать таким образом, чтобы можно было переоценить require('settings.json') в модулях, использующих объект конфигурации после его импорта:

export default function getConfig() {
  return require('settings.json');
}

getConfig() всегда следует использовать как есть, его не следуетназначенный const config = getConfig() в верхней части модуля, в котором он используется, это сделает его недоступным для кэширования.

В настоящее время способ восстановить исходную конфигурацию - это изменить ее, сохранив ссылку на существующий объект, например:

afterEach(() => {
  decache('./settings.json');
  Object.assign(Config, require('./settings.json'));
});

Как видно.Абстракция Config.get ничего не помогает.

Другой способ в транспортируемом модуле ES - это непосредственное исправление объекта модуля.Поскольку объект модуля должен быть отражением экспорта только для чтения в соответствии со спецификациями.Ожидается, что модули обрабатываются соответствующим образом транспиляторами, включая TypeScript.Это зависит от того, как создается приложение, и может не работать должным образом в любой среде.

import Config from './config';
console.log(Config.foo);

должно быть перенесено в нечто вроде

Object.defineProperty(exports, "__esModule", { value: true });    
console.log(config_1.default.foo;);

Это может позволить отключить модуль ESэкспортирует динамически (не возможно для экспорта модуля CommonJS по умолчанию) и влияет на те части модуля, которые используют Config и переоцениваются (например, внутри функций, но не в области видимости модуля верхнего уровня):

afterEach(() => {
  decache('./settings.json');
  const configModule = require('./config'));
  configModule.default = require('./settings.json');
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...