#dependency-injection #junit #isolation
#внедрение зависимостей #junit #изоляция
Вопрос:
Я имею дело со случаем, когда мои тесты проходят или завершаются неудачей в зависимости от порядка объявления. Это, конечно, указывает на неправильно изолированные тесты. Но я в тупике по поводу того, как найти проблему. Дело в том, что мои тесты junit являются производными от класса, который принадлежит платформе тестирования, построенной на junit, и имеет некоторый контейнер для внедрения зависимостей. Контейнер сбрасывается для каждого теста с помощью настройки базового класса, и поэтому в контейнере, по крайней мере, в контейнере, нет устаревших объектов, поскольку сам контейнер является новым. Итак, я склоняюсь к следующему сценарию.
- test1 косвенно вызывает некоторый ClassA, который устанавливает ClassA.somestaticMember в значение xyz. test obj не поддерживает никаких ссылок на ClassA напрямую, но ClassA по-прежнему загружается виртуальной машиной со значением xyz по завершении test1.
- test2 обращается к ClassA и отключает somestaticmember, имеющий значение xyz.
Проблема в том, что а) я не знаю, действительно ли это так — как мне это найти? Кажется, я не могу найти ссылку на статический var в коде… б) есть ли способ сообщить junit о сбросе всех своих загруженных классов и сделать это заново для каждого метода тестирования?
Комментарии:
1. Если ваши тесты завершаются неудачно в зависимости от порядка выполнения, то они не являются настоящими модульными тестами. Это, или вы не используете преимущества приспособлений.
Ответ №1:
Вы можете объявить метод с @Before
помощью, например
@Before public void init()
{
// set up stuff
}
и JUnit будет запускать его перед каждым тестом. Вы можете использовать это для настройки «приспособления» (известного набора новых объектов, данных и т. Д., С Которыми ваши тесты будут работать независимо друг от друга).
Существует также @After
, который вы можете использовать для выполнения любой очистки, необходимой после каждого теста. Обычно вам не нужно этого делать, поскольку Java очистит все используемые вами объекты, но это может быть полезно для восстановления внешних объектов (материалов, которые вы не создаете и не управляете) до известного состояния.
(Однако обратите внимание: если вы полагаетесь на внешние объекты для выполнения своих тестов, то то, что у вас есть, больше не является модульным тестом. Вы не можете точно сказать, вызван ли сбой вашим кодом или внешним объектом, и это одна из целей модульных тестов.)
Комментарии:
1. Я согласен — это не «модульный» тест. Это скорее функциональный / интеграционный тест, поскольку я использую полные внешние объекты. Однако я не имею большого права голоса в этом вопросе. Простое тестирование стало большим улучшением, в отличие от отсутствия. Я использую junit 3.8 и методы установки и демонтажа, но что касается внешних объектов, как мне выполнить повторную инициализацию?
2. @treefrog: зависит от вашей инфраструктуры DI и / или ваших объектов. Вы должны иметь возможность либо заменить объекты известными новыми, либо «сбросить» существующие — вручную, если это необходимо. Например, если вашим внешним объектом является база данных, удалите все старые данные, а затем вставьте достаточно данных для выполнения всех ваших тестов. Или для файлов удалите файл или поместите его обратно или замените его известной версией. Для сетевых проблем закройте соединение и перезапустите его. Суть в том, чтобы отменить любые побочные эффекты , которые могут вызвать ваши тесты — среда должна быть точно такой же для каждого теста.
3. да, я понимаю, что это то, что мне нужно сделать — я искал способы добиться этого — предоставляет ли junit способ указать отдельный загрузчик классов для загрузочных тестов? или, может быть, мне нужно перебрать все классы, загруженные загрузчиком классов, и очистить их с помощью отражения — я не могу придумать другого способа