MockMvc configure a header for all requests

isADon picture isADon · May 25, 2018 · Viewed 18.6k times · Source

In my tests I setup the MockMvc object in the @Before like this

mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .apply(springSecurity())
                .build();

In every request I do I always need to send the same headers. Is there a way to configure the headers the MockMvc will use globally or per test class?

Answer

BigDaddy picture BigDaddy · Nov 29, 2018

I do not know if it still relevant, but I stumbled over the same problem. We added an API key authentication to a REST api afterwards, and all tests (mainly with @AutoConfigureMockMvc) needed to be adjusted with using a proper API (on top of the new tests, testing that the keys are working).

Spring uses their Customizers and Builders pattern also when creating the MockMvc, like it is done with RestTemplateBuilder and RestTemplateCustomizer.

You are able to create a @Bean/@Component that is a org.springframework.boot.test.autoconfigure.web.servlet.MockMvcBuilderCustomizerand it will get picked up during the bootstrap process of your @SpringBootTests.

You can then add a parent defaultRequetsBuilders that are merged with the specific RequestBuilders when running the test.

Sample Customizer that adds a header

package foobar;


import org.springframework.boot.test.autoconfigure.web.servlet.MockMvcBuilderCustomizer;
import org.springframework.stereotype.Component;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;

/**
 * Whenever a mockmvc object is autoconfigured, this customizer should be picked up, and a default, usable, working, valid api key is set as
 * default authorization header to be applied on all tests if not overwritten.
 *
 */
@Component
public class ApiKeyHeaderMockMvcBuilderCustomizer implements MockMvcBuilderCustomizer {

    @Override
    public void customize(ConfigurableMockMvcBuilder<?> builder) {
        // setting the parent (mergeable) default requestbuilder to ConfigurableMockMvcBuilder
        // every specifically set value in the requestbuilder used in the test class will have priority over
        // the values set in the parent. 
        // This means, the url will always be replaced, since "any" would not make any sense.
        // In case of multi value properties (like headers), existing headers from our default builder they are either merged or appended,
        // exactly what we want to achieve
        // see https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/web/servlet/MockMvcBuilderCustomizer.html
        // and https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/Mergeable.html
        RequestBuilder apiKeyRequestBuilder = MockMvcRequestBuilders.get("any")
            .header("api-key-header", "apikeyvalue");
        builder.defaultRequest(apiKeyRequestBuilder);
    }

}

Hope that helps.