web-dev-qa-db-fra.com

MockMvc configure un en-tête pour toutes les demandes

Dans mes tests, j'ai configuré l'objet MockMvc dans le @Before comme ça

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

Dans chaque demande que je fais, j'ai toujours besoin d'envoyer les mêmes en-têtes. Existe-t-il un moyen de configurer les en-têtes que MockMvc utilisera globalement ou par classe de test?

6
isADon

Que diriez-vous de faire une classe d'usine pour commencer avec votre demande déjà décroissante avec en-têtes? Étant donné que MockHttpServletRequestBuilder est un générateur, il vous suffit de décorer la demande avec l'une des propriétés supplémentaires (paramètres, type de contenu, etc.) dont vous avez besoin. Le constructeur est conçu juste à cet effet! Par exemple:

public class MyTestRequestFactory {

    public static MockHttpServletRequestBuilder myFactoryRequest(String url) {
        return MockMvcRequestBuilders.get(url)
                .header("myKey", "myValue")
                .header("myKey2", "myValue2");
    }
}

Puis dans votre test:

@Test
public void whenITestUrlWithFactoryRequest_thenStatusIsOK() throws Exception {

    mockMvc()
        .perform(MyTestRequestFactory.myFactoryRequest("/my/test/url"))
        .andExpect(status().isOk());
}

@Test
public void whenITestAnotherUrlWithFactoryRequest_thenStatusIsOK() throws Exception {

    mockMvc()
        .perform(MyTestRequestFactory.myFactoryRequest("/my/test/other/url"))
        .andExpect(status().isOk());
}

Chaque test appellera le noeud final avec les mêmes en-têtes.

5
Dovmo

Je ne sais pas si c'est toujours pertinent, mais je suis tombé sur le même problème. Nous avons ajouté une authentification par clé API à une REST api par la suite, et tous les tests (principalement avec @AutoConfigureMockMvc) devaient être ajustés à l'aide d'une API appropriée (en plus des nouveaux tests, testant que le les touches fonctionnent).

Spring utilise également leur modèle de personnalisateurs et de constructeurs lors de la création de MockMvc, comme cela se fait avec RestTemplateBuilder et RestTemplateCustomizer.

Vous pouvez créer un @ Bean/@ Component qui est un org.springframework.boot.test.autoconfigure.web.servlet.MockMvcBuilderCustomizeret il sera récupéré pendant le processus bootstrap de vos @SpringBootTests.

Vous pouvez ensuite ajouter un parent DefaultRequetsBuilders qui est fusionné avec les RequestBuilders spécifiques lors de l'exécution du test.

Exemple de personnalisateur qui ajoute un en-tête

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);
    }

}

J'espère que cela pourra aider.

4
BigDaddy
this.mockMvc = MockMvcBuilders.webAppContextSetup(context).apply(new HttpHeaderMockMvcConfigurer()).build();

public class HttpHeaderMockMvcConfigurer extends MockMvcConfigurerAdapter {
    @Override
    public RequestPostProcessor beforeMockMvcCreated(ConfigurableMockMvcBuilder<?> builder, WebApplicationContext cxt) {
        builder.defaultRequest(MockMvcRequestBuilders.post("test").header("appId", "aaa"));
        return super.beforeMockMvcCreated(builder, cxt);
    }
}

Définissez les propriétés de demande par défaut qui doivent être fusionnées dans toutes les demandes effectuées. En effet, cela fournit un mécanisme pour définir une initialisation commune pour toutes les demandes telles que le type de contenu, les paramètres de demande, les attributs de session et toute autre propriété de demande.

1
minjay26

Vous pouvez écrire une implémentation de javax.servlet.Filter . Dans votre cas, vous pouvez ajouter les en-têtes à votre demande. MockMvcBuilders a une méthode pour ajouter des filtres:

mockMvc = MockMvcBuilders.webAppContextSetup(context)
            .apply(springSecurity())
            .addFilter(new CustomFilter(), "/*")
            .build();
0
borino