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

4

假设我有一个名为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个回答

3
您可以采用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);
    
        }

1

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

public class MockTenantInterceptor extends HandlerInterceptorAdapter

我们可以在不进行自动装配的情况下初始化模拟拦截器类,并将其注册到TestConfiguration类中。请确保添加Spring Profile注释,以防止生产拦截器被调用,因为我们将有两个配置类,一个是WebConfig,另一个是TestConfig。
@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

1

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

private MockMvc mockMvc;

@MockBean
private MyInterceptor interceptor;

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接