HTTP 클라이언트 테스트를 위한 WireMock - Test MockServer
클라언트에서 서버로 요청하는 프로그램을 개발하고 테스트를 하기 위해 대상 서버가 필요하다.
테스트 과정에서 서버에서 일어나는 일은 관심이 없다. 응답 후 테스트가 주요 목적일 것이다.
그래서 실제 서버로 테스트하지 않고 모의 서버를 이용하여 테스트하면 된다.
모의 서버를 구성하고 테스트하는 방법에 대해 가이드하였다.
테스트를 위한 모의 서버를 제공하는 라이브러리는 WireMock 과 MockServer 두가지가 있는 데 WireMock 을 사용하여 예제를 작성하였다. 그리고 Spring cloud 의존성을 사용하면 wiremock 이 포함되어 있으니 참고한다.
설치
standalone 버전이 있는 데 이건 WireMock 를 독립적으로 실행하여 Mock Server 를 운영할 수 있는 버전으로 보여진다. 그래서 일반 버전을 사용한다.
testCompile "com.github.tomakehurst:wiremock-jre8:2.31.0"
나는 Spring cloud 를 사용하므로 아래와 같이 설정했다.
ext.springCloudVersion = "Hoxton.SR11"
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
testImplementation "org.springframework.cloud:spring-cloud-starter-contract-stub-runner"
WireMock 포트 설정
@AutoConfigureWireMock(port = 0)
AutoConfigureWireMock 선언으로 스프링 설정을 자동 구성할 수 있다.
WireMock서버용 포트를 직접 설정할 수 있지만 랜덤 포트 사용을 권장하고 있다.
하지만 랜덤 포트를 사용하면 실제 서버의 포트와 다를 수 있어 properties를 재설정 해야한다.
아래와 같은 방법으로 해결할 수 있다.
@AutoConfigureWireMock(port = 0)
@TestPropertySource(properties = {
"app.gateway-uri=http://localhost:${wiremock.server.port}"
})
반복되는 설정 코드를 줄이기 위해 아래와 같이 선언방식으로 사용하면 된다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigureWireMock(port = 0)
@TestPropertySource(properties = {
"app.gateway-uri=http://localhost:${wiremock.server.port}"
})
public @interface WireMockTest {
}
WireMock은 요청과 응답을 stub이란 템플릿 파을을 구성하여 사용할 수 있다.
stub은 json 구조의 문법을 사용하며 동적인 부분은 handlebars.java 템플릿 엔진의 문법을 사용할 수 있다.
stub 파일의 기본 경로는 classpath:/mappings
이며 AutoConfigureWireMock 선언에서 경로를 변경할 수 있다. stub 경로의 하위 모든 json 파일을 읽는다.
sample-stub.json
{
"mappings": [
{
"request": {
"method": "GET",
"urlPathPattern": "/account/v1/users/duplicate-username",
"queryParameters": {
"username": {
"matches": ".*"
}
}
},
"response": {
"headers" : {
"Content-Type" : "text/plain"
},
"status": 200,
"body": "true"
}
}
]
}
matches와 같은 속성은 요청 값에 대한 유효성 검증을 할 수 있다. 그외에 다양한 속성을 제공하니 가이드를 참고한다. 참고 - http://wiremock.org/docs/request-matching/
유효성 검증은 필수가 아니다. 필요할거나 요청을 명확하게 하려면 유효성 검증을 설정하는 것이 좋다.
테스트 코드에서 GET /account/v1/users/duplicate-username?username=test
요청하면 응답와 같은 응답을 받을 수 있다.
HTTP/1.1 200 OK
Content-Type: text/plain
true
matches 속성에 의해 username 파라메터에 값이 없으면 오류가 발생한다.
response body 가 문자열인 경우이며 json 인 경우는 jsonBody 속성을 사용해야 한다.
그외에도 다양한 속성이 있으니 가이드를 참고한다.
참고 - http://wiremock.org/docs/response-templating/
stub 의 스크립트적인 문법은 Handlebars.java 템플릿 엔진을 기반이라 동적인 문법도 사용이 가능하다.
사용하려면 응답에 아래와 같이 추가해야 한다.
"transformers": ["response-template"],
예를 들어 request 데이터를 response 에서 사용할 수 있다.
{
"request": {
"method": "POST",
"url": "/account/v1/managers"
},
"response": {
"headers" : {
"Content-Type" : "application/json"
},
"transformers": ["response-template"],
"status": 201,
"jsonBody": {
"id" : 1,
"username" : "{{jsonPath request.body '$.username'}}",
"name" : "{{jsonPath request.body '$.name'}}",
"registeredOn" : "{{#assign 'dateTimeFormat'}}yyyy-MM-dd'T'HH:mm:ss.SSSSSS{{/assign}}{{now format=dateTimeFormat}}",
"updatedOn" : null
}
}
}
참고
- http://wiremock.org/docs
- https://docs.spring.io/spring-cloud-contract/docs/current/reference/html/project-features.html#features-wiremock
- https://www.baeldung.com/spring-cloud-feign-integration-tests
- https://github.com/wiremock/wiremock/blob/master/src/main/java/com/github/tomakehurst/wiremock/http/ResponseDefinition.java
'Tech' 카테고리의 다른 글
OAuth 2.0 Simplified (0) | 2021.10.18 |
---|---|
자주 사용하는 Git CLI (Command line interface) (0) | 2021.10.15 |
OpenFegin Example (0) | 2021.10.07 |
Java Database Connection TLS 보안 이슈 (0) | 2021.10.07 |