You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring-WS端点的JUnit测试中Mock Service类

解决方案:Mock Spring SOAP Endpoint中的依赖

要Mock CountryRepository,核心思路是在测试上下文里替换掉真实的Repository实例,让Endpoint使用Mock对象而非真实的数据库依赖。下面提供两种常用的实现方式:

方法一:使用Mockito + Spring测试工具替换Bean

这种方法适合传统Spring项目(非Spring Boot),通过Mockito创建Mock实例,再替换Spring管理的Endpoint中的依赖:

  1. 添加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>
    
  2. 修改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,可以创建测试专属的上下文配置:

  1. 创建测试配置文件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>
    
  2. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:50:07