Search code examples
javaspring-bootjunitwiremockspring-cloud-contract

How to use different mapping files for different test methods?


I am using Wiremock (spring-cloud-contract-wiremock) in my @SpringBootTest so:

import static com.github.tomakehurst.wiremock.client.WireMock.*;

@SpringBootTest
@AutoConfigureWireMock(port = 0)
class SomeTest {

    @Test
    void test1() {
        Wiremock.stubFor(get(urlPathEqualTo("/endpoint"))
                .willReturn(aResponse().withStatus(200))
        );

        //  start test
        //  assertThat response is 200
    }

    @Test
    void test2() {
        stubFor(get(urlPathEqualTo("/endpoint"))
                .willReturn(aResponse().withStatus(401))
        );

        // start test
        // assertThat response is 401
    }
}

Thus, for two test methods I make different stubs for the same request and it works well.

Also, when using Wiremock, you can store stubs in JSON format in the src/test/resources/mappings package, but so far I can only achieve such a result that I can only have one JSON file in which I store the stubs.

How can I have two separate JSON for two test methods and how can I tell my test method to use a specific JSON file to load Wiremock-stubs?

I am using spring-boot-parent 3.1.0 and this maven dependency for WireMock:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-contract-wiremock</artifactId>
    <version>4.0.2</version>
    <scope>test</scope>
</dependency>

Solution

    1. Solution with spring-cloud-contract-wiremock:
    import static com.github.tomakehurst.wiremock.client.WireMock.*;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
    
    @SpringBootTest
    @AutoConfigureWireMock(port = 0)
    class SomeTest {
    
        @Autowired
        private WireMockServer wireMockServer;
    
        @BeforeEach
        void setUp() {
            wireMockServer.resetAll();
        }
    
        @Test
        void test1() {
            String json = <json with mappings for 200 and others>;
    
            Json.read(json, new TypeReference<List<StubMapping>>(){})
                    .forEach(wireMockServer::addStubMapping);
    
            //  start test
            //  assertThat response is 200
        }
    
        @Test
        void test2() {
            String json = <json with mappings for 401 and others>;
    
            Json.read(json, new TypeReference<List<StubMapping>>(){})
                    .forEach(wireMockServer::addStubMapping);
    
            // start test
            // assertThat response is 401
        }
    }
    
    1. Solution with manual creating of WireMockServer:
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.github.tomakehurst.wiremock.WireMockServer;
    import com.github.tomakehurst.wiremock.common.Json;
    import com.github.tomakehurst.wiremock.stubbing.StubMapping;
    import org.junit.jupiter.api.AfterAll;
    import org.junit.jupiter.api.BeforeAll;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.springframework.test.context.DynamicPropertyRegistry;
    import org.springframework.test.context.DynamicPropertySource;
    
    import java.util.List;
    
    import static com.github.tomakehurst.wiremock.client.WireMock.configureFor;
    import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
    
    public class WiremockTest {
    
        private static final WireMockServer WIRE_MOCK_SERVER = new WireMockServer(wireMockConfig().dynamicPort());
    
        @DynamicPropertySource
        static void dynamicPropertySource(DynamicPropertyRegistry dynamicPropertyRegistry) {
            dynamicPropertyRegistry.add("wiremock.server.base-url", WIRE_MOCK_SERVER::baseUrl);
    
         //  with it we can change url in our application.yml
         //  like so: {wiremock.server.base-url}/endpoint
        }
    
        @BeforeAll
        static void startWireMock() {
            WIRE_MOCK_SERVER.start();
        }
    
        @AfterAll
        static void stopWireMock() {
            WIRE_MOCK_SERVER.stop();
    
        }
    
        @BeforeEach
        void clearWireMock() {
            WIRE_MOCK_SERVER.resetAll();
        }
    
        @Test
        void test1() {
            String json = <json with mappings for 200 and others>;
            
            Json.read(json, new TypeReference<List<StubMapping>>(){})
                    .forEach(WIRE_MOCK_SERVER::addStubMapping);
    
            //  start test
            //  assertThat response is 200
        }
    
        @Test
        void test2() {
            String json = <json with mappings for 401 and others>;
    
            Json.read(json, new TypeReference<List<StubMapping>>(){})
                    .forEach(WIRE_MOCK_SERVER::addStubMapping);
            
            // start test
            // assertThat response is 401
        }
    }
    

    Format of json must be following:

    [
      {
        "request": {
          "urlPath": "/endpoint",
          "method": "GET"
        },
        "response": {
          "status": 200,
          "jsonBody": {
            "foo": "bar"
          },
          "headers": {
            "Content-Type": "application/json"
          }
        }
      },
      {
        "request": {
          "urlPath": "/endpoint",
          "method": "PATCH"
        },
        "response": {
          "status": 202,
          "headers": {
            "Content-Type": "application/json"
          }
        }
      }
    ]