반응형

운영 환경에서 사용하기

build.gradle.kts

extra["springCloudVersion"] = "2022.0.4"

dependencies {
    ...
    implementation("org.springframework.cloud:spring-cloud-starter-contract-stub-runner")
}

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
    }
}

WireMockConfig

@Configuration
public class WireMockConfig {
    private final Logger log = LoggerFactory.getLogger(WireMockConfig.class);

    @Bean(initMethod = "start", destroyMethod = "stop")
    public WireMockServer wireMockServer() throws IOException {
        log.info("[WIRE_MOCK_CONFIG] start");

        WireMockServer wireMockServer = new WireMockServer(WireMockSpring.options().disableRequestJournal().port(19090));
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("wiremock/**/*.json");

        for (Resource resource : resources) {
            log.info("[WIRE_MOCK_CONFIG] jsonFilePath : {}", resource.getURL().getPath());
            wireMockServer.addStubMapping(StubMapping.buildFrom(IOUtils.toString(resource.getInputStream())));
        }

        log.info("[WIRE_MOCK_CONFIG] finish");
        return wireMockServer;
    }
}

Mocking

JavaConfig를 활용한 방법

@RequiredArgsConstructor
@Configuration
public class DemoApiMocking {
    private final WireMockServer wireMockServer;

    @PostConstruct
    public void mocking() {
        wireMockServer.stubFor(
            WireMock.post(WireMock.urlPathMatching("/api/demo/(.*?)"))
                .withRequestBody(WireMock.equalToJson("{\"name\":  \"john\"}"))
                .willReturn(
                    WireMock.aResponse()
                        .withStatus(200)
                        .withHeader("Content-Type", MediaTypes.APPLICATION_JSON)
                        .withBody("{\"message\": \"Hi, john\"}")
                )
        );
    }
}

json 파일을 활용한 방법

  • 경로 : ~/src/main/resources/wiremock/demo-api-mocking.json
    {
      "request": {
        "urlPathPattern": "/api/demo/(.*?)",
        "method": "POST",
        "bodyPatterns": [
          {
            "equalToJson": {
              "name": "john"
            }
          }
        ]
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json"
        },
        "jsonBody": {
          "message": "Hi, john"
        }
      }
    }

Test

RestTemplate restTemplate = new RestTemplate();

ResponseEntity<String> result = restTemplate.exchange("http://localhost:19090/api/demo/john", HttpMethod.POST, new HttpEntity<>("{\"name\": \"john\"}"), String.class);
String body = result.getBody();

System.out.println(body); // {"message": "Hi, john"}

참고

테스트 케이스에서 사용하기

src/test/resources/application-unittest.properties

demo.url=http://localhost:${wiremock.server.port}

Java 코드로 모킹하여 테스트

WireMockTest

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
@ActiveProfiles("unittest")
public class WireMockTest {
    @Value("${demo.url}")
    private String demoUrl;

    @Test
    public void demo() throws Exception {
//        WireMock.stubFor(
//            WireMock.get(WireMock.urlPathEqualTo("/api/v1/demo"))
//                .willReturn(WireMock.aResponse()
//                    .withStatus(HttpStatus.OK.value())
//                    .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
//                    .withBody(Files.readString(ResourceUtils.getFile("classpath:payload/demo-body.json").toPath()))
//                )
//        );

        WireMock.stubFor(
            WireMock.get(WireMock.urlPathEqualTo("/api/v1/demo"))
                .willReturn(WireMock.aResponse()
                    .withStatus(HttpStatus.OK.value())
                    .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
                    .withBody("{\"name\":\"tyler\", \"age\": 50}")
                )
        );

        RestTemplate restTemplate = new RestTemplate();
        Map result = restTemplate.getForObject(demoUrl + "/api/v1/demo", Map.class);

        System.out.println(result.get("name")); // tyler
        System.out.println(result.get("age")); // 50
    }
}

json 파일로 모킹하여 테스트

src/test/resources/stubs/demo-v1.json

{
  "request": {
    "method": "GET",
    "url": "/api/v1/demo"
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "jsonBody": {
      "name": "tyler",
      "age": 50
    }
  }
}

WireMockTest

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 0, stubs = "classpath:/stubs")
@ActiveProfiles("unittest")
public class WireMockTest {
    @Value("${demo.url}")
    private String demoUrl;

    @Test
    public void demo() {
        RestTemplate restTemplate = new RestTemplate();
        Map result = restTemplate.getForObject(demoUrl + "/api/v1/demo", Map.class);

        System.out.println(result.get("name")); // tyler
        System.out.println(result.get("age")); // 50
    }
}
반응형

'Development > Spring' 카테고리의 다른 글

[Spring] Elasticsearch  (0) 2024.01.01
[Spring] 헥사고날 아키텍처(Hexagonal Architecture)  (2) 2023.11.23
[Spring] SpEL  (0) 2023.08.09
[Spring] actuator  (0) 2021.11.27
[Spring] Scheduler Lock  (0) 2021.11.25

+ Recent posts