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. 使用*@ContextConfigurationresources*

我们可以通过将测试配置文件放在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. 使用*@ContextConfigurationWEB-INF*

我们还可以从WEB-INF目录在测试类中导入应用程序上下文。为此,我们可以使用其file URL引用应用程序上下文:

@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/application-context.xml")

4. 总结

本文介绍了如何在Spring Boot应用的测试类中使用XML配置文件。如往常一样,本文所使用的源代码可在GitHub上找到。