How to test a Spring Boot handler Interceptor
Asked Answered
S

2

14

we are trying to do an intergration test our interceptors in our spring boot application using spring boot version 1.4.0, but not sure how; here is our application setting

@Configuration
@EnableAutoConfiguration()
@ComponentScan
public class Application extends SpringBootServletInitializer {
  @Override
  protected SpringApplicationBuilderconfigure(SpringApplicationBuilder application) {
  return application.sources(Application.class);
}

we then customed out webmvc by extending WebMvcConfigurerAdapter

@Configuration
public class CustomServletContext extends WebMvcConfigurerAdapter{
  @Override
  public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(testInterceptor).addPathPatterns("/testapi/**");
  }
}

so we wanna to test the interceptor, but we don't wanna really start the application, cause there are many dependency beans that need to read a externally defined property files to construct

we have tried the following

@SpringBootTest(classes = CustomServletContext.class)
@RunWith(SpringRunner.class)
public class CustomServletContextTest {

  @Autowired
  private ApplicationContext applicationContext;

  @Test
  public void interceptor_request_all() throws Exception {
    RequestMappingHandlerMapping mapping = (RequestMappingHandlerMapping) applicationContext
        .getBean("requestMappingHandlerMapping");
    assertNotNull(mapping);

    MockHttpServletRequest request = new MockHttpServletRequest("GET",
        "/test");

    HandlerExecutionChain chain = mapping.getHandler(request);

    Optional<TestInterceptor> containsHandler = FluentIterable
        .from(Arrays.asList(chain.getInterceptors()))
        .filter(TestInterceptor.class).first();

    assertTrue(containsHandler.isPresent());
  }
}

but it alters org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'requestMappingHandlerMapping' is defined

Do we need to create a bean of requestMappingHandlerMapping to test the interceptors? is there any magical way to do this in spring boot ?

Stemma answered 2/10, 2017 at 18:9 Comment(6)
What are you trying to test? Spring? Why would you do that? Your TestInterceptor? If so, create an instance of it and call the HandlerInterceptor methods and verify outcome. That's called Unit Testing, i.e. testing the Unit, aka the TestInterceptor.Biathlon
what we wanna test is our interceptor is actually only intercepting the configured urls, like this leveluplunch.com/blog/2014/07/09/…, but we can not use "@SpringApplicationConfiguration(classes=Application.class) " as in the exampleStemma
So you want to test that Spring correctly applies the "/testapi/**" pattern correctly, i.e. you want to test Spring? Again, why?Biathlon
you are right, cause we are not sure about using /testapi/* or testapi/**Stemma
Well, should it match /testapi/foo/bar? If no, use /testapi/*. If yes, use /testapi/**.Biathlon
what stops you from testing both and seeing which one works?Bouldon
M
4

You can create a test like this :

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { MyIncludedConfig.class })
@ActiveProfiles("my_enabled_profile")
public class BfmSecurityInterceptorTest2 {

    public static final String TEST_URI = "/test";
    public static final String RESPONSE = "test";

    // this way you can provide any beans missing due to limiting the application configuration scope
    @MockBean
    private DataSource dataSource;

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    public void testInterceptor_Session_cookie_present_Authorized() throws Exception {

        ResponseEntity<String> responseEntity = testRestTemplate.getForEntity(TEST_URI, String.class);

        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(responseEntity.getBody()).isEqualTo(RESPONSE);

    }

    @SpringBootApplication
    @RestController
    public static class TestApplication {

        @GetMapping(TEST_URI)
        public String test() {
            return RESPONSE;
        }

    }

}

Notes

  • Interceptors only work if you set SpringBootTest.WebEnvironment.RANDOM_PORT
  • You have to provide enough configuration so your interceptors are executed
  • To speed up the test you can exclude not wanted beans and configurations, see examples
Manley answered 2/8, 2019 at 11:29 Comment(0)
V
0
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertTrue;

@SpringBootTest()
class LoggingInterceptorConfigurationTest {

    @Autowired
    private RequestMappingHandlerMapping mapping;

    @Test
    public void LoggingInterceptorShouldBeApplied() throws Exception {

        MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/example");

        HandlerExecutionChain chain = mapping.getHandler(request);

        assert chain != null;
        Optional<HandlerInterceptor> LoggingInterceptor = chain.getInterceptorList()
                .stream()
                .filter(LoggingInterceptor.class::isInstance)
                .findFirst();

        assertTrue(LoggingInterceptor.isPresent());
    }

    @Test
    public void LoggingInterceptorShouldNotBeAppliedToHealthURL() throws Exception {

        MockHttpServletRequest request = new MockHttpServletRequest("GET", "/health");

        HandlerExecutionChain chain = mapping.getHandler(request);

        assert chain != null;
        Optional<HandlerInterceptor> LoggingInterceptor = chain.getInterceptorList()
                .stream()
                .filter(LoggingInterceptor.class::isInstance)
                .findFirst();

        assertTrue(LoggingInterceptor.isEmpty());
    }

}
Vmail answered 28/5, 2022 at 14:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.