С jUnit 4 можно ли параметризовать @BeforeClass?
Я использую jUnit для управления интеграционными тестами для приложения, которое обращается к базе данных. Поскольку настройка тестовых данных - это трудоемкая операция, я делаю это в методе @BeforeClass
, который выполняется только один раз для каждого тестового класса (в отличие от метода @Before
, который запускается один раз для каждого метода тестирования).
Теперь я хочу попробовать несколько разных перестановок для настройки уровня данных, выполнив все мои тесты в каждой другой конфигурации. Это кажется естественным использованием тестового бегунка Parameterized
. Проблема заключается в том, что Parameterized
поставляет параметры конструктору класса, а метод @BeforeClass
является абстрактным и вызывается перед конструктором класса.
Несколько вопросов,
Вызывает ли Parameterized
метод @BeforeClass
для каждой перестановки параметров или вызывает ли он только один раз?
Если метод @BeforeClass
вызывается повторно, есть ли способ получить доступ к значениям параметров изнутри?
Если ни один из них, что люди считают лучшим альтернативным подходом к этой проблеме?
Ответы
Ответ 1
Я думаю, вам понадобится пользовательский тестовый бегун. У меня та же проблема, с которой вы сталкиваетесь (нужно запускать те же тесты с использованием нескольких дорогостоящих конфигураций). Вам понадобится способ параметризации настройки, возможно, используя аннотации @Parameter, аналогичные тем, которые используются параметризуемым бегуном, но по статическим полям-членам вместо полей экземпляра. Пользовательский бегун должен будет найти все статические поля-члены с аннотацией @Parameter, а затем запустить тестовый класс (возможно, используя базовый BlockJunit4ClassRunner) один раз в статическом поле @Parameter. Поле @Parameter должно быть @ClassRule.
Andy on Software отлично поработала над созданием пользовательских тестовых бегунов, и он так ясно объясняет эти сообщения в блоге здесь и здесь.
Ответ 2
@BeforeClass вызывается только один раз в вашем примере. Что имеет смысл, учитывая имя - перед классом!
Если ваши тесты требуют разных данных, есть два варианта, о которых я могу думать:
- Настройте эти данные в @Before так, чтобы они были специфичны для тестирования
- Группируйте тесты, которые вы хотите запускать с одними и теми же данными, в отдельные классы тестов и используйте @BeforeClass для каждого из них.
Ответ 3
Вы можете вызвать эту логику инициализации в конструкторе вашего тестового класса. Следите за последним параметром, используемым в статической переменной. Когда он изменится, настройте класс для нового параметра.
Я не могу придумать эквивалент для AfterClass.
Ответ 4
Это старый вопрос, но мне просто пришлось решить, вероятно, подобную проблему. На данный момент я пошел с решением ниже, которое по существу представляет собой реализацию ответа TREE (обновленный) с использованием общего абстрактного базового класса, чтобы избежать дублирования всякий раз, когда вам нужен этот механизм.
Конкретные тесты предоставили бы метод @Parameters, который возвращает итерабельность одноэлементных массивов, содержащих Поставщик <T> каждый. Затем эти поставщики выполняются ровно один раз на фактический ввод, необходимый для конкретных методов тестирования.
@RunWith(Parameterized.class)
public class AbstractBufferedInputTest<T> {
private static Object INPUT_BUFFER;
private static Object PROVIDER_OF_BUFFERED_INPUT;
private T currentInput;
@SuppressWarnings("unchecked")
public AbstractBufferedInputTest(Supplier<T> inputSuppler) {
if (PROVIDER_OF_BUFFERED_INPUT != inputSuppler) {
INPUT_BUFFER = inputSuppler.get();
PROVIDER_OF_BUFFERED_INPUT = inputSuppler;
}
currentInput = (T) INPUT_BUFFER;
}
/**
*
* @return the input to be used by test methods
*/
public T getCurrentInput() {
return currentInput;
}
}
Ответ 5
Вы можете выполнить инициализацию в методе @Before, записывая переменную экземпляра, но проверяя значение null.
@RunWith(value = Parameterized.class)
public class BigThingTests {
private BigThing bigThing;
@Before
public void createBitThing() {
if (bigThing == null) {
bigThing = new BigThing();
}
}
...
}
Для каждого набора параметров создается новый экземпляр BigThingTests
, а bigThing
устанавливается с нулевым значением с каждым новым экземпляром. Бегун Parameterized
является однопоточным, поэтому вам не нужно беспокоиться о нескольких инициализациях.