1. 概述
在Spring Boot应用中,bean的混合定义包括了基于注解([Annotation-Based](/spring-core-annotations))和基于XML([XML-Based](/spring-boot-xml-beans))的配置。在这种环境中,我们可能希望在测试类中使用基于XML的配置。然而,有时会遇到ApplicationContext
加载失败的错误:“Failed to load ApplicationContext”。这是因为测试上下文并未加载应用程序上下文。
本文将讨论如何在Spring Boot应用中整合XML应用程序上下文进行测试。
2. “Failed to load ApplicationContext” 错误
让我们通过在Spring Boot应用中集成基于XML的应用上下文来重现这个错误。
首先,假设我们有一个名为application-context.xml
的文件,其中定义了一个服务bean:
<?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>
然后,我们将application-context.xml
文件放在webapp/WEB-INF/
目录下:
接下来,我们会创建一个服务接口和类:
public interface EmployeeService {
Employee getEmployee();
}
public class EmployeeServiceImpl implements EmployeeService {
@Override
public Employee getEmployee() {
return new Employee("Baeldung", "Admin");
}
}
最后,我们将创建一个获取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
这个错误出现在测试类中,因为测试上下文没有加载应用程序上下文。而且,根本原因是WEB-INF
目录未包含在类路径中:
@ContextConfiguration(locations={"classpath:WEB-INF/application-context.xml"})
3. 在测试中使用基于XML的ApplicationContext
现在来看看如何在测试类中使用基于XML的ApplicationContext。我们在测试中使用XML-Based ApplicationContext
有两种选择:@SpringBootTest 注解和@ContextConfiguration 注解。
3.1. 使用*@SpringBootTest和@ImportResource*
Spring Boot提供了*@SpringBootTest*
注解,用于创建在测试中使用的应用程序上下文。此外,我们需要在Spring Boot主类中使用*@ImportResource*
注解来读取XML bean定义。此注解允许我们导入包含bean定义的一个或多个资源。
首先,在主类中使用*@ImportResource*
注解:
@SpringBootApplication
@ImportResource({"classpath*:application-context.xml"})
然后,我们创建一个从ApplicationContext获取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配置创建我们的测试上下文。
在这种情况下,我们可以使用*@ContextConfiguration*
注解从src/test/resources
目录加载测试上下文。
首先,我们从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*
我们还可以从WEB-INF
目录在测试类中导入应用程序上下文。为此,我们可以使用其file
URL引用应用程序上下文:
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/application-context.xml")
4. 总结
本文介绍了如何在Spring Boot应用的测试类中使用XML配置文件。如往常一样,本文所使用的源代码可在GitHub上找到。