Reputation: 34900
Say I have some FooInterceptor
:
public class FooInterceptor extends HandlerInterceptorAdapter {
// ...
}
Which is configured in the context:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="my.package.FooInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
I am creating an integration test for some controller:
@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();
}
...
}
I have tried to mock it via creating a custom configuration:
@Configuration
static class Config {
@Bean
@Primary
public FooInterceptor getFooInterceptor() {
return mock(FooInterceptor.class);
}
}
But it doesn't seem to me to be working. The actual FooInterceptor
is still produced and involved into the test.
How to properly mock it?
Upvotes: 4
Views: 9533
Reputation: 321
You can go with the following as suggested by Luana FM in the previous answer. Also you'll need one line of mock code to return the response of interceptor as true in @BeforeEach
block.
@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);
}
Upvotes: 3
Reputation: 1589
So I went ahead and wrote some code to solve the same question I had. Within our test case project, We can mock the interceptor by explicitly defining our own interceptor that extends HandlerInterceptorAdapter which will have mock logic mimicking our original interceptor
public class MockTenantInterceptor extends HandlerInterceptorAdapter
We can initialize the mock interceptor class without autowiring and proceed to register it within TestConfiguration class. Do make sure since we will have 2 configuration classes one for WebConfig and TestConfig to add the spring profile annotation that prevents your production interceptor from been invoked.
@Profile("test")
@TestConfiguration
@EnableJpaAuditing
public class TestConfig extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
MockTenantInterceptor mockTenantInterceptor = new MockTenantInterceptor();
registry.addInterceptor(mockTenantInterceptor);
}
}
Edit: With Spring 5 / Spring Boot 2, extends WebMvcConfigurerAdapter
has been deprecated in favor of implements WebMvcConfigurer
and uses Java 8's new default methods for interfaces.
See https://www.baeldung.com/web-mvc-configurer-adapter-deprecated
Upvotes: 1
Reputation: 336
Isn't just injecting the interceptor an easier, cleaner way?
private MockMvc mockMvc;
@MockBean
private MyInterceptor interceptor;
@BeforeEach
public void before() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(controller)
.addInterceptors(interceptor)
.build();
}
Upvotes: 1