【问题标题】:How to mock Spring HandlerInterceptorAdapter in an integration test?如何在集成测试中模拟 Spring HandlerInterceptorAdapter?
【发布时间】:2018-03-25 10:24:50
【问题描述】:

说我有一些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 仍会生成并参与测试。

如何正确地模拟它?

【问题讨论】:

    标签: java spring mocking integration-testing interceptor


    【解决方案1】:

    您可以按照 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);
        
            }
    

    【讨论】:

      【解决方案2】:

      注入拦截器不就是一种更简单、更清洁的方法吗?

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

      【讨论】:

        【解决方案3】:

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

        public class MockTenantInterceptor extends HandlerInterceptorAdapter
        

        我们可以在没有自动装配的情况下初始化模拟拦截器类,然后在 TestConfiguration 类中注册它。请确保我们将有 2 个配置类,其中一个用于 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);
            }
        }
        

        编辑:在 Spring 5 / Spring Boot 2 中,extends WebMvcConfigurerAdapter 已被弃用,取而代之的是 implements WebMvcConfigurer,并使用 Java 8 的新默认接口方法。

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

        【讨论】:

          猜你喜欢
          • 2015-12-14
          • 2018-08-14
          • 2019-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-30
          • 2012-04-25
          • 1970-01-01
          相关资源
          最近更新 更多