#javascript #testing #jestjs #rewire
#javascript #тестирование #jestjs #переподключите
Вопрос:
Я хотел бы иметь возможность изолировать побочные эффекты, которые, по-видимому, связаны при тестировании двух функций, которые изменяют одну и ту же переменную состояния myVar
независимо друг от друга.
example.js
export function foobar() {
sideEffect1();
sideEffect2();
}
let myVar;
function sideEffect1() {
if (myVar === undefined) {
myVar = 'foo';
}
}
function sideEffect2() {
if (myVar === undefined) {
myVar = 'bar';
}
}
example.test.js
import example, {return2} from "../src/example";
test('Test Side Effect 1', () => {
let se = example.__get__('sideEffect1');
se();
let myVar = example.__get__('myVar');
expect(myVar).toBe("foo");
});
test('Test Side Effect 2', () => {
let se = example.__get__('sideEffect2');
se();
let myVar = example.__get__('myVar');
expect(myVar).toBe("bar");
});
Вывод
> jest "js/tests/example.test.js"
FAIL js/tests/example.test.js (6.056 s)
✓ Test Side Effect 1 (1 ms)
✕ Test Side Effect 2 (4 ms)
● Test Side Effect 2
expect(received).toBe(expected) // Object.is equality
Expected: "bar"
Received: "foo"
23 | se();
24 | let myVar = example.__get__('myVar');
> 25 | expect(myVar).toBe("bar");
| ^
26 | });
27 |
28 |
Если я запускаю каждый тест отдельно, оба работают нормально. Проблема, похоже, заключается в запуске всего набора тестов.
Это упрощение той же проблемы, которая у меня есть в коде, который используется в более сложном приложении. Есть идеи, почему и как это можно решить?
babel.config.json
{
"presets": ["@babel/preset-env"],
"plugins": ["babel-plugin-rewire"]
}
Комментарии:
1. а) не используйте модули с отслеживанием состояния б) имейте функцию для инициализации переменной в произвольное состояние и сброса ее перед каждым тестом в) удалите модуль из кэша и повторно
require
его.2. Если вы уже используете
rewire
(не так ли?), Тогда просто используйте__set__
!3. Да, я использую rewire (с babel), я только что добавил параметры конфигурации. Тогда я мог бы вручную сбросить эту переменную через set . Это хорошая практика для этого? Что касается «состояния», то это соображение дизайна, поскольку в исходном коде эта переменная используется для хранения текущего состояния для операции во время сеанса с браузером. Ваше замечание по этому поводу все еще применимо? есть ли что-то еще, что нужно улучшить, или это был обходной путь только для теста? спасибо!
4. Что касается использования set, вы имеете в виду это?
example.__set__('sideEffect1', "myCustomValue")
Я не могу сбросить значение рассматриваемой переменной таким образом.5. Я бы сказал, что наилучшей практикой было бы переместить состояние в
Session
класс, который вы создаете один раз в своем приложении и несколько раз в тестах. Но если это действительно глобальное состояние окна браузера, может быть неплохо поместить его в модуль. Вам просто нужно иметь возможность сбросить его для тестов (и, возможно, также для какой-то функции выхода из системы). Тесты станут интеграционными тестами, а не модульными тестами.
Ответ №1:
Модули загружаются в начале выполнения и загружаются как один — так что ваш example.js выполняется правильно, независимо от того, какая функция выполняется первой sideEffect1
или sideEffect2
эта функция устанавливает переменную myVar
, и затем вы получаете значение этой переменной