JUnit 测试时加载 ApplicationContext 失败
1、概览
在 Spring Boot 应用中,可以同时包含基于注解和基于 XML 的配置来混合定义 Bean。在这种环境中,如果你在测试类中使用基于 XML 的配置可能会遇到 “Failed to load ApplicationContext” 异常。因为 Application Context 没有加载到 Test Context 中。
本文将会带你了解如何把 XML Application Context 集成到 Spring Boot 应用的测试中。
2、“Failed to load ApplicationContext” 异常
在 Spring Boot 应用中集成基于 XML 的 Application Context 来重现该异常。
首先,假设有一个包含 Service Bean 定义的 application-context.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="employeeServiceImpl" class="com.baeldung.xmlapplicationcontext.service.EmployeeServiceImpl" />
</beans>
在 webapp/WEB-INF/
位置添加 application-context.xml
文件:
再创建一个 Service 接口和实现类:
public interface EmployeeService {
Employee getEmployee();
}
public class EmployeeServiceImpl implements EmployeeService {
@Override
public Employee getEmployee() {
return new Employee("Baeldung", "Admin");
}
}
最后,创建一个测试用例,用于从 Application Context 中获取 EmployeeService
Bean:
@RunWith(SpringRunner.class)
@ContextConfiguration(locations={"classpath:WEB-INF/application-context.xml"})
public class EmployeeServiceAppContextIntegrationTest {
@Autowired
private EmployeeService service;
@Test
public void whenContextLoads_thenServiceISNotNull() {
assertThat(service).isNotNull();
}
}
现在,如果尝试运行这个测试,就会遇到异常:
java.lang.IllegalStateException: Failed to load ApplicationContext
出现这个异常,是因为 Application Context 没有加载到 Test Context 中。此外,根本原因是 classpath 中未包含 WEB-INF
:
@ContextConfiguration(locations={"classpath:WEB-INF/application-context.xml"})
3、在测试中使用基于 XML 的 ApplicationContext
在测试中使用基于 XML 的 ApplicationContext
时,有两种选择: @SpringBootTest
和 @ContextConfiguration
注解。
3.1、测试使用 @SpringBootTest
和 @ImportResource
Spring Boot 提供了 @SpringBootTest
注解,可以用它来创建 Application Context,以便在测试中使用。此外,还必须在 Spring Boot main 类中使用 @ImportResource
来读取 XML Bean。该注解允许导入一个或多个包含 Bean 定义的资源。
在 main 类中使用 @ImportResource
注解导入 xml 配置:
@SpringBootApplication
@ImportResource({"classpath*:application-context.xml"})
现在,创建测试用例,从 Application Context 中获取 EmployeeService
Bean:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = XmlBeanApplication.class)
public class EmployeeServiceAppContextIntegrationTest {
@Autowired
private EmployeeService service;
@Test
public void whenContextLoads_thenServiceISNotNull() {
assertThat(service).isNotNull();
}
}
@ImportResource
注解会加载 resource
目录中的 XML Bean。@SpringBootTest
注解会在测试类中加载整个应用的 Bean。因此,可以在测试类中访问 EmployeeService
Bean。
3.2、使用 @ContextConfiguration
与 resources
进行测试
可以将测试配置文件放在 src/test/resources
目录中,创建具有不同 Bean 配置的 Test Context。
在本例中,使用 @ContextConfiguration
注解从 src/test/resources
目录加载 Test Context。
首先,实现 EmployeeService
接口创建另一个 Bean:
public class EmployeeServiceTestImpl implements EmployeeService {
@Override
public Employee getEmployee() {
return new Employee("Baeldung-Test", "Admin");
}
}
然后,在 src/test/resources
目录中创建 test-context.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="employeeServiceTestImpl" class="process.service.EmployeeServiceTestImpl" />
</beans>
最后,创建测试用例:
@SpringBootTest
@ContextConfiguration(locations = "/test-context.xml")
public class EmployeeServiceTestContextIntegrationTest {
@Autowired
@Qualifier("employeeServiceTestImpl")
private EmployeeService serviceTest;
@Test
public void whenTestContextLoads_thenServiceTestISNotNull() {
assertThat(serviceTest).isNotNull();
}
}
如上,使用 @ContextConfiguration
注解从 test-context.xml
中加载了 employeeServiceTestImpl
。
3.3、使用 @ContextConfiguration
和 WEB-INF
进行测试
还可以在测试类中使用 file
URL 从 WEB-INF
目录导入 Application Context。
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/application-context.xml")
4、总结
本文介绍了如何在 Spring Boot 应用的测试中使用基于 XML 的配置文件。
参考:https://www.baeldung.com/spring-junit-failed-to-load-applicationcontext