如何在Spring控制器集成测试中Mock HandlerInterceptorAdapter?
如何在Spring集成测试中Mock HandlerInterceptorAdapter?
针对你现在的场景——用XML配置的FooInterceptor,并且集成测试用了@WebAppConfiguration和SpringJUnit4ClassRunner,我给你梳理两种实用的方案:
方法一:用@MockBean快速替换(推荐,适用于Spring 4.3+或Spring Boot)
如果你的Spring版本在4.3及以上,或者项目是Spring Boot的话,@MockBean绝对是最省事的办法。它会自动帮你把Spring上下文中的FooInterceptor实例替换成Mockito的Mock对象,完全不用改原有的XML配置。
直接在测试类里这么写就行:
@WebAppConfiguration @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "/context.xml") @ActiveProfiles(...) public class YourControllerIntegrationTest { // 用@MockBean标记,Spring会自动替换上下文中的真实实例 @MockBean private FooInterceptor fooInterceptor; // 注入测试用的MockMvc,用来模拟请求 @Autowired private MockMvc mockMvc; @Test public void testControllerWithMockedInterceptor() throws Exception { // 先指定拦截器的行为,比如让preHandle返回true,避免拦截请求 when(fooInterceptor.preHandle(any(HttpServletRequest.class), any(HttpServletResponse.class), any(Object.class))) .thenReturn(true); // 模拟请求你的控制器接口 mockMvc.perform(get("/your/controller/path")) .andExpect(status().isOk()); // 还能验证拦截器的方法有没有被调用 verify(fooInterceptor, times(1)) .preHandle(any(HttpServletRequest.class), any(HttpServletResponse.class), any(Object.class)); } }
方法二:传统XML上下文覆盖(适用于旧版Spring)
如果你的Spring版本比较老,不支持@MockBean,那可以创建一个测试专用的XML配置,覆盖原有的拦截器定义:
- 新建一个
test-context.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" 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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 覆盖原拦截器配置,用Mockito创建Mock实例 --> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean id="fooInterceptor" class="org.mockito.Mockito" factory-method="mock"> <constructor-arg value="my.package.FooInterceptor"/> </bean> </mvc:interceptor> </mvc:interceptors> <!-- 导入原来的上下文,保证其他业务bean不受影响 --> <import resource="/context.xml"/> </beans>
- 然后在测试类里指定这个测试上下文:
@WebAppConfiguration @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(value = "/test-context.xml") @ActiveProfiles(...) public class YourControllerIntegrationTest { // 这里注入的就是Mock的拦截器实例了 @Autowired private FooInterceptor fooInterceptor; @Autowired private MockMvc mockMvc; @Test public void testControllerWithMockedInterceptor() throws Exception { // 设置Mock行为,和第一种方法一样 when(fooInterceptor.preHandle(any(HttpServletRequest.class), any(HttpServletResponse.class), any(Object.class))) .thenReturn(true); // 执行测试请求 mockMvc.perform(get("/your/controller/path")) .andExpect(status().isOk()); // 验证拦截器方法调用 verify(fooInterceptor).preHandle(any(), any(), any()); } }
注意:两种方法都需要确保你的测试依赖里包含mockito-core,不然没法创建Mock对象哦。
内容的提问来源于stack exchange,提问作者Andremoniy
相关产品推荐
相关产品推荐

