有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在集成测试中模拟Spring HandlerInterceptorAdapter?

假设我有一些FooInterceptor

public class FooInterceptor extends HandlerInterceptorAdapter {
   // ...
}

这是在上下文中配置的:

 <mvc:interceptors>
     <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="my.package.FooInterceptor"/>
     </mvc:interceptor>
 </mvc:interceptors>

我正在为某个控制器创建一个集成测试:

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "/context.xml")
@ActiveProfiles("test")
public class SomeControllerIT {

    @Autowired
    private WebApplicationContext webApplicationContext;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(webApplicationContext)
                .apply(springSecurity())
                .build();
    }

    ...
}

我试图通过创建自定义配置来模拟它:

@Configuration
static class Config {

    @Bean
    @Primary
    public FooInterceptor getFooInterceptor() {
        return mock(FooInterceptor.class);
    }
}

但在我看来,它似乎不起作用。实际的FooInterceptor仍在生成并参与测试

如何恰当地嘲笑它


共 (3) 个答案

  1. # 1 楼答案

    所以我继续写了一些代码来解决我的问题。在我们的测试用例项目中,我们可以通过显式定义我们自己的拦截器来模拟拦截器,该拦截器扩展了HandlerInterceptorAdapter,该拦截器将具有模拟原始拦截器的模拟逻辑

    public class MockTenantInterceptor extends HandlerInterceptorAdapter
    

    我们可以在不自动连接的情况下初始化模拟拦截器类,并继续在TestConfiguration类中注册它。一定要确保,因为我们将有两个配置类,一个用于WebConfig和TestConfig,以添加spring概要文件注释,防止调用生产拦截器

    @Profile("test")
    @TestConfiguration
    @EnableJpaAuditing
    public class TestConfig extends WebMvcConfigurerAdapter {
    
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            MockTenantInterceptor mockTenantInterceptor = new MockTenantInterceptor();
            registry.addInterceptor(mockTenantInterceptor);
        }
    }
    

    编辑:在Spring5/SpringBoot2中,extends WebMvcConfigurerAdapter被弃用,取而代之的是implements WebMvcConfigurer,并使用Java8新的默认接口方法

    https://www.baeldung.com/web-mvc-configurer-adapter-deprecated

  2. # 2 楼答案

    你可以按照Luana FM在上一个答案中的建议进行以下操作。此外,在@BeforeEach块中,还需要一行模拟代码将拦截器的响应返回为true

            @BeforeEach
            public void before() {
              MockitoAnnotations.initMocks(this);
              mockMvc = MockMvcBuilders
                  .standaloneSetup(controller)
                  .addInterceptors(interceptor)
                  .build();
            when(interceptor.preHandle(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(true);
        
            }
    
  3. # 3 楼答案

    注入拦截器不是一种更简单、更干净的方法吗

    private MockMvc mockMvc;
    
    @MockBean
    private MyInterceptor interceptor;
    
    @BeforeEach
    public void before() {
      MockitoAnnotations.initMocks(this);
      mockMvc = MockMvcBuilders
          .standaloneSetup(controller)
          .addInterceptors(interceptor)
          .build();
    }