Я новичок в Spring и работаю с набором интеграционных тестов JUnit 4.7 для веб-приложения. У меня есть несколько рабочих тестовых примеров в форме:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/META-INF/spring/testContext.xml" })
public class myTest {
@Test
public void testCreate() {
//execute tests
....
}
}
Мое приложение имеет ряд внешних зависимостей, которые я тестирую, все из которых имеют bean-компоненты, которые инициализируются посредством загрузки testContext.xml . Некоторые из этих внешних зависимостей требуют настраиваемого кода для инициализации и удаления необходимых ресурсов.
Вместо того, чтобы дублировать этот код в каждом тестовом классе, который требует его, я хотел бы инкапсулировать его в общее место. Я думал о создании отдельного определения контекста, а также настраиваемого средства выполнения, которое расширяет SpringJUnit4ClassRunner и содержит аннотацию @ContextConfiguration и связанный с ним настраиваемый код, например:
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
//load the context applicable to this runner
@ContextConfiguration(locations = { "/META-INF/spring/testContext.xml" })
public class MyCustomRunner extends SpringJUnit4ClassRunner {
public MyCustomRunner(Class<?> clazz) throws InitializationError {
super(clazz);
}
@Override
protected Statement withBeforeClasses(Statement statement) {
// custom initialization code for resources loaded by testContext.xml
...
return super.withBeforeClasses(statement);
}
@Override
protected Statement withAfterClasses(Statement statement) {
// custom cleanup code for resources loaded by testContext.xml
....
return super.withAfterClasses(statement);
}
}
Затем я мог бы указать для каждого тестового класса своего применимого бегуна с помощью:
@RunWith(MyCustomRunner)
Когда я это сделаю, мои тесты будут выполняться, и будут выполнены соответствующие методы withBeforeClasses и withAfterClasses . Однако в тестовый класс не возвращается applicationContext, и все мои тесты завершаются неудачно с:
java.lang.IllegalArgumentException: Не удается загрузить ApplicationContext с NULL 'contextLoader'. Рассмотреть возможность аннотирование вашего тестового класса с помощью @ContextConfiguration.
Контекст загружается правильно, только если я указываю аннотацию @ContextConfiguration для каждого тестового класса - в идеале я бы хотел, чтобы эта аннотация жила с кодом обработчика для ресурсов, за загрузку которых она отвечает. Это приводит меня к моему вопросу - можно ли загрузить контекстную информацию Spring из пользовательского класса runner?