How to use different mapping files for different test methods?

400 views Asked by At

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>
3

There are 3 answers

0
Georgii Lvov On BEST ANSWER
  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"
      }
    }
  }
]
1
lance-java On

You could use ResponseDefinitionBuilder.withBodyFile(fileName) which will source files, by default, from src/test/resources

@Test
void test1() {
   Wiremock.stubFor(
      get(urlPathEqualTo("/endpoint")).willReturn(
         aResponse()
            .withStatus(200)
            .withBodyFile("SomeTest/test1.json")
   );
   ...
}
0
lance-java On

You could do

@SpringBootTest
class SomeTest {
   private WireMockServer wireMockServer;

   @Before
   public void before() {
      wireMockServer = new WireMockServer(<port>);
   }

   @After
   public void after() {
      wireMockServer.resetAll();
      wireMockServer.stop();
   }

   @Test
   public void test1() {
      wireMockServer.addStubMapping(buildStubMapping("SomeTest/test1.json"));
      // test 1 specific assertions
   }

   @Test 
   public void test2() {
      wireMockServer.addStubMapping(buildStubMapping("SomeTest/test2.json"));
      // test 2 specific assertions
   }

   private StubMapping buildStubMapping(String path) {
      Resource resource = new ClassPathResource(path);
      String json = IOUtils.toString(resource.getInputStream());
      return StubMapping.buildFrom(json);
   }
}