Search code examples
spring-securityspring-test-mvc

Spring MVC Test MockMvc - how do I configure a url mapping prefix


I have a DispatcherServlet that has a URL mapping /api1 and subsequentially a Controller with a mapping @GetMapping("/resource1") for a controller method. So basically I have a valid URL /api1/resource1 that should be handled by the mentioned controller.

Also, the setup incorporates a Spring Security Filter that matches requests /* as it secures other URLs not handled by Spring (but Jersey for example). The API secured by the Spring Security Filter is setup like

    protected void configure(HttpSecurity http) throws Exception {
        //@formatter:off
        http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .requestMatchers()
                .antMatchers("/api1/**")
            .and()
            .authorizeRequests()
                .antMatchers("/**")
                .authenticated()

For testing I use the MockMvc* support to setup a mocked web environment including a Spring security setup

mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity())
                .build()

I want to test that security checks are applied and the controller method is called on successful security checks.

        when:
        def result = mvc.perform(
                get('/api1/resource1')
                    .header(HttpHeaders.AUTHORIZATION,  "Bearer " + apiToken))

        then:
          result.andExpect(status().isOk())

The code above is based on the Spock framework with the MockMvc stuff. All of the security checks are passing so the Spring security setup is complete, but finally the controller should be invoked but fails with a 404 status i.e the resource - this is the mapped controller method - is not found.

I'm confident that it fails because the mocked setup does not incorporate a the /api dispatcher servlet mapping. To proof that assumption I can modify the controller method mapping to @GetMapping("/api1/resource1") and the test will result in a HTTP OK (200).

So, my question is, is it possible to configure a kind of URL prefix in the MockMvc setup? There is one constraint, the code base is not using Spring Boot (and can't for a while in future)!

Edit: I added the following to my test to have all requests set the servletPath.

    static MockHttpServletRequestBuilder get(String urlTemplate, Object... uriVars) {
        new MockHttpServletRequestBuilder(HttpMethod.GET, urlTemplate, uriVars)
                .servletPath('/api1')
    }

Solution

  • I think you just need to configure the contextPath for the request.

    See org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder.contextPath(String) for details.