13

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 ?

sthbuilder
  • 561
  • 1
  • 7
  • 22
  • 2
    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`. – Andreas Oct 02 '17 at 18:17
  • what we wanna test is our interceptor is actually only intercepting the configured urls, like this https://www.leveluplunch.com/blog/2014/07/09/how-to-test-spring-mvc-handler-interceptors/, but we can not use "@SpringApplicationConfiguration(classes=Application.class) " as in the example – sthbuilder Oct 02 '17 at 18:28
  • So you want to test that Spring correctly applies the `"/testapi/**"` pattern correctly, i.e. you want to test Spring? Again, why? – Andreas Oct 02 '17 at 18:34
  • you are right, cause we are not sure about using /testapi/* or testapi/** – sthbuilder Oct 02 '17 at 18:57
  • Well, should it match `/testapi/foo/bar`? If no, use `/testapi/*`. If yes, use `/testapi/**`. – Andreas Oct 02 '17 at 18:59
  • what stops you from testing both and seeing which one works? – Andrii Plotnikov Oct 03 '17 at 13:36

2 Answers2

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
Peter Szanto
  • 7,568
  • 2
  • 51
  • 53
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());
    }

}
Pradeep Nooney
  • 740
  • 10
  • 12