如何在Spring-WS端点的JUnit测试中Mock Service类
解决方案:Mock Spring SOAP Endpoint中的依赖
要Mock CountryRepository,核心思路是在测试上下文里替换掉真实的Repository实例,让Endpoint使用Mock对象而非真实的数据库依赖。下面提供两种常用的实现方式:
方法一:使用Mockito + Spring测试工具替换Bean
这种方法适合传统Spring项目(非Spring Boot),通过Mockito创建Mock实例,再替换Spring管理的Endpoint中的依赖:
添加Mockito依赖
确保你的项目依赖中包含Mockito核心及Spring支持包(以Maven为例):<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>3.2.18.RELEASE</version> <scope>test</scope> </dependency>修改JUnit测试类
调整测试逻辑,创建Mock Repository并替换Endpoint中的真实依赖:@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/spring-context.xml") public class CountryEndpointTest { // 注意:原类名建议和Endpoint对应,改为CountryEndpointTest @Autowired private ApplicationContext applicationContext; @Autowired private ResourceLoader resourceLoader; @Autowired private CountryEndPoint countryEndPoint; // 注入要测试的Endpoint private MockWebServiceClient mockClient; private Resource schema = new ClassPathResource("countries.xsd"); private CountryRepository mockCountryRepository; @Before public void setup() { // 创建Mock的Repository实例 mockCountryRepository = Mockito.mock(CountryRepository.class); // 用Spring测试工具替换Endpoint中的countryRepository字段 ReflectionTestUtils.setField(countryEndPoint, "countryRepository", mockCountryRepository); // 初始化MockWebServiceClient mockClient = MockWebServiceClient.createClient(applicationContext); } @Test public void testCountryEndpoint() throws Exception { // 定义Mock行为:当调用findCountry("TestCountry")时返回预设对象 Country mockCountry = new Country(); mockCountry.setName("TestCountry"); mockCountry.setCapital("TestCapital"); Mockito.when(mockCountryRepository.findCountry("TestCountry")).thenReturn(mockCountry); Resource request = resourceLoader.getResource("request.xml"); Resource response = resourceLoader.getResource("response.xml"); mockClient.sendRequest(withPayload(request)) .andExpect(payload(response)) .andExpect(validPayload(schema)); // 验证Repository方法是否被正确调用一次 Mockito.verify(mockCountryRepository, Mockito.times(1)).findCountry("TestCountry"); } }这里用
ReflectionTestUtils(Spring内置测试工具)直接替换Endpoint中的依赖字段,无需修改原有业务代码,同时可以通过Mockito验证方法调用情况。
方法二:使用测试专用Spring配置文件
如果你更倾向于通过Spring配置管理Mock Bean,可以创建测试专属的上下文配置:
创建测试配置文件
spring-context-test.xml<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:sws="http://www.springframework.org/schema/web-services" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.tutorialspoint" /> <sws:annotation-driven /> <!-- 用Mockito创建Mock的CountryRepository Bean,替换真实实现 --> <bean id="countryRepository" class="org.mockito.Mockito" factory-method="mock"> <constructor-arg value="com.tutorialspoint.CountryRepository" /> </bean> <bean id="schema" class="org.springframework.core.io.ClassPathResource"> <constructor-arg index="0" value="*.xsd" /> </bean> </beans>修改JUnit测试类的上下文配置
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "/spring-context-test.xml") // 加载测试配置 public class CountryEndpointTest { @Autowired private ApplicationContext applicationContext; @Autowired private ResourceLoader resourceLoader; @Autowired private CountryRepository countryRepository; // 注入Mock的Repository private MockWebServiceClient mockClient; private Resource schema = new ClassPathResource("countries.xsd"); @Before public void createClient() { mockClient = MockWebServiceClient.createClient(applicationContext); } @Test public void testCountryEndpoint() throws Exception { // 定义Mock行为 Country mockCountry = new Country(); mockCountry.setName("TestCountry"); mockCountry.setCapital("TestCapital"); Mockito.when(countryRepository.findCountry("TestCountry")).thenReturn(mockCountry); Resource request = resourceLoader.getResource("request.xml"); Resource response = resourceLoader.getResource("response.xml"); mockClient.sendRequest(withPayload(request)) .andExpect(payload(response)) .andExpect(validPayload(schema)); Mockito.verify(countryRepository).findCountry("TestCountry"); } }这种方式通过Spring配置直接生成Mock Bean,无需手动替换字段,适合需要在多个测试类中复用Mock配置的场景。
额外提示
如果是Spring Boot项目,可以直接使用@MockBean注解,它会自动替换Spring上下文中的对应Bean,写法更简洁:
@MockBean private CountryRepository countryRepository;
内容的提问来源于stack exchange,提问作者Bhaskar Varada
相关产品推荐
相关产品推荐

