|
Чтобы не подымать руками контекст Spring-а в каждом модульном
тесте на JUnit, был придуман SpringJUnit4ClassRunner. Но его использование делает невозможным применение еще одного очень
плезного запускальщика тестов: Parameterized. И тут возникает проблема,
как усидеть на двух стульях сразу: писать параметризованные тесты и
пользоваться Spring.
|
JUnit,
Положим, у нас есть интерфейс, для которого есть масса
разных реализаций. И нам бы хотелось написать тест, проверяющий поведение всех
реализаций (убедиться, что все реализации ведут себя одинаково).
@RunWith(Parameterized.class)
public class ExampleTest {
@Parameters
public static Collection getParameters() {
return parameters;
}
@Test
public void test() {
/* Выполняем проверку поведения */
asserNotNull(implementation.doSomething());
}
public ExampleTest(MyInterface implementation) {
this.implementation = implementation;
}
private MyInterface implementation;
private static Collection parameters = Arrays.asList(new Object[] {
{ new MyImplementation1() }, { new MyImplementation2() } });
}
При этом, хотелось бы вынести инстанцирование в конфигурационный файл spring-а.
Что ты делаешь?!
Прежде всего, инициализацию класса с тестами придется взять на себя. И первый порыв поиметь счастье, засунув код инициализации в @BeforeClass public static void setUpClass() заканчивается неудачей.
@RunWith(Parameterized.class)
public class ExampleTest {
@BeforeClass
public static void setUpClass() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:spring-config.xml");
implementations = (List<String>) context.getBean("implementations");
}
@Parameters
public static Collection getParameters() {
return implementations;
}
}
@Parameters public static Collection getParameters() вызывается раньше.
АХАХАХА!
К тому же, getParameters() должен возвращать коллекцию массивов.
@RunWith(Parameterized.class)
public class ExampleTest {
@Parameters
public static Collection getParameters() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:spring-config.xml");
implementations = (List<MyInterface>) context.getBean("arguments");
return Arrays.asList(new Object[] {implementations.toArray()});
}
...
}
Но, очевидно, этот код не корректен в силу того, что мы хотим, чтобы каждый элемент implementations был единственным параметром теста, но по правилам JUnit, параметр теста должен быть элементом массива Object, который, в свою очередь, является элементом коллекции. В приведенном же примере получается так, что каждый элемент implementations является отдельным параметром одного теста. Т.е. на каждый элемент из implementations требуется аргумент в конструкторе.
ПРЕКРАТИ.
@RunWith(Parameterized.class)
public class ExampleTest {
@Parameters
public static Collection getParameters() {
if (implementations == null) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:spring-config.xml");
implementations = (List<MyInterface>) context.getBean("implementations");
parameters = implementations.toArray();
for (int i = 0; i < parameters.length; i++) {
parameters[i] = new Object[] { parameters[i] };
}
}
return Arrays.asList(parameters);
}
@Test
public void test() {
/* Выполняем проверку поведения */
asserNotNull(implementation.doSomething());
}
public ExampleTest(MyInterface implementation) {
this.implementation = implementation;
}
private MyInterface implementation;
private static Collection<MyInterface> implementations;
private static Object[] parameters;
}
Вот в таком виде цель будет достигнута, но чистотой и ясностью такой код уже, увы, не блещет.
Комментариев нет:
Отправить комментарий