如何Mock Aspect切面类的方法,避免Controller测试触发不必要的数据库调用
解决方案
你可以根据测试场景选择以下任意一种方案实现需求:
方案1:直接Mock整个切面类(最推荐,适配Controller切片测试场景)
如果你的测试是@WebMvcTest切片测试或者@SpringBootTest集成测试,直接用Spring Boot提供的@MockBean注解替换容器中的真实切面实例,自定义切面方法的逻辑完全跳过原有数据库操作即可:
import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.web.servlet.MockMvc; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @WebMvcTest(SampleController.class) class SampleControllerTest { // 将容器中的SampleAspect替换为Mock对象 @MockBean private SampleAspect sampleAspect; @Autowired private MockMvc mockMvc; @Test void testgetdata() throws Exception { // 定义Mock的拦截方法行为:直接执行目标Controller方法,完全跳过原有切面逻辑 when(sampleAspect.interceptor(any(ProceedingJoinPoint.class))) .thenAnswer(invocation -> { ProceedingJoinPoint point = invocation.getArgument(0); return point.proceed(); }); // 执行接口测试逻辑 mockMvc.perform(get("/123")) .andExpect(status().isOk()) .andExpect(content().string("hello")); } }
该方案会完全屏蔽原有切面的所有逻辑,包括内部的数据库操作、对HandlerInterceptor实现类的调用,不需要额外处理切面的内部依赖。
方案2:仅Mock切面的内部依赖
如果你需要保留切面本身的逻辑,仅屏蔽数据库调用和HandlerInterceptor的真实执行,可以只Mock切面依赖的数据库操作类、以及对应的HandlerInterceptor实现类:
@WebMvcTest(SampleController.class) class SampleControllerTest { // Mock切面内部调用的数据库操作Mapper/DAO @MockBean private OperateLogMapper operateLogMapper; // Mock切面内部调用的HandlerInterceptor实现类 @MockBean private CustomHandlerInterceptor customHandlerInterceptor; @Autowired private MockMvc mockMvc; @Test void testgetdata() throws Exception { // 给Mock依赖定义默认返回值 when(operateLogMapper.insert(any())).thenReturn(1); when(customHandlerInterceptor.preHandle(any(), any(), any())).thenReturn(true); // 执行测试即可,切面逻辑正常执行但不会触发真实外部调用 mockMvc.perform(get("/123")) .andExpect(status().isOk()); } }
方案3:纯单元测试Controller
如果你的测试不需要启动Spring上下文,只是单元测试Controller的业务方法,直接手动实例化Controller调用方法即可,这种场景下切面根本不会被加载,自然不会触发拦截逻辑:
class SampleControllerTest { private final SampleController sampleController = new SampleController(); @Test void testgetdata() { String result = sampleController.getdata("123"); Assertions.assertEquals("hello", result); } }
注意事项
如果出现Mock切面不生效的情况,检查测试类是否开启了AspectJ自动代理,Spring Boot默认已经开启,特殊场景可以手动在测试类上加@EnableAspectJAutoProxy注解即可。
内容的提问来源于stack exchange,提问作者Stack Overflow
相关产品推荐
相关产品推荐

