Переменные модуля не понятны между тестами в шутку

#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 , и затем вы получаете значение этой переменной