概述
在开发中,我们需要mock Http API,主要有两种使用场景:
- 前后端分离开发,API first,可以提供虚拟接口,方便前端开发。
- 集成测试依赖其他模块API,自己Mock Http接口。
WireMock就是一个比较比较适合做此场景的测试框架。它是java语言编写,可以在JUnit中使用,也可以独立部署HTTP服务运行。
一、Junit集成
示例
public class SampleTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
@Test
public void wireMockExampleTest() throws IOException, JSONException {
String restposeJson = "{\"hello\":\"ok http\"}";
stubFor(get(urlEqualTo("/my/resource"))
.withHeader("Accept", equalTo("application/json"))
.willReturn(aResponse()
.withStatus(200)
.withBody(restposeJson)));
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://localhost:8089/my/resource")
.addHeader("Accept", "application/json")
.build();
Response response = client.newCall(request).execute();
assertTrue(response.isSuccessful());
assertEquals(response.code(), 200);
JSONAssert.assertEquals(restposeJson, response.body().string(), false);
verify(1, getRequestedFor(urlEqualTo("/my/resource"))
.withHeader("Accept", equalTo("application/json")));
}
}
wiremock模拟一个端口8089的服务,通过stbFor打桩,使用okHttpClient发起请求,对返回值断言和验证。
二、单独起服务
1. 启动
wireMock还提供了WireMock server,通过命令启动:
java -jar wiremock-standalone-2.6.0.jar
管理地址:
2. 模拟API
POST请求
如果想尽快Mock一个API,可以通过curl、postman、chrome的wiremock插件快速POST数据到wiremock server。如下curl示例:
curl -X POST \
--data '{ "request": { "url": "/get/this", "method": "GET" }, "response": { "status": 200, "body": "Here it is!\n" }}' \
http://localhost:8080/__admin/mappings/new
POST成功后,检查模拟的API:
➜ ~ curl http://localhost:8080/get/this -i
HTTP/1.1 200 OK
Vary: Accept-Encoding, User-Agent
Transfer-Encoding: chunked
Server: Jetty(9.2.z-SNAPSHOT)
Here it is!
编写文件
启动mocke server 后,相同目录下生产__files
和mappings
两个目录:
- mappings:存放mock文件
- __files:存放mock文件中指定的body
cat mappings/hello_get.json
{
"request": {
"method": "GET",
"url": "/api/mytest"
},
"response": {
"status": 200,
"body": "More content\n"
}
}
curl http://localhost:8080/api/mytest
HTTP/1.1 200 OK
Vary: Accept-Encoding, User-Agent
Transfer-Encoding: chunked
Server: Jetty(9.2.z-SNAPSHOT)
More content
单独启动服务两个好处:
- 快速模拟API,语言无关,可以给所有的开发团队使用
- 由服务提供者编写并维护mappings下的json文件,方便其他模块开发和集成测试。
3. 其他方式启动
docker 启动
docker run -it -p 8080:8080 -d rodolpheche/wiremock
maven plugin
<plugin>
<groupId>uk.co.deliverymind</groupId>
<artifactId>wiremock-maven-plugin</artifactId>
<version>${wiremock-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
<configuration>
<dir>target/classes</dir>
<params>--port=8081</params>
</configuration>
</execution>
</executions>
</plugin>
mock 定义文件目录:
src/main/resources/mappings/
src/main/resources/__files/
三、spring-cloud-contract
spring-cloud-contract 是一个消费驱动设计工具。不管是自己mock还是通过一个中间服务mock,都有一个共同的问题,需要开发者同步维护mock,否则对一个老的mock API测试,结果毫无意义。
spring cloud contract 通过在生产者一方编写stub mapping,编译时自动生成一个jar包(http-server.1.0.1.stubs.jar),而消费方自动引入此包作为test的stub,这样,生产者每次修改代码,只要产生新stub,消费者都会自动获取,省去了双方沟通和一致的问题。
下面是一个简单示例: Server / Producer side
package com.example;
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc;
public class MvcTest {
@Before
public void setup() {
RestAssuredMockMvc.standaloneSetup(new FraudDetectionController());
}
}
在src/test/resources/contracts
使用groovy定义stub。
如:shouldMarkClientAsFraud.groovy
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'PUT'
url '/fraudcheck'
body("""
{
"clientId":"1234567890",
"loanAmount":99999
}
""")
headers {
header('Content-Type', 'application/vnd.fraud.v1+json')
}
}
response {
status 200
body("""
{
"fraudCheckStatus": "FRAUD",
"rejectionReason": "Amount too high"
}
""")
headers {
header('Content-Type': 'application/vnd.fraud.v1+json')
}
}
}
maven test会做2个工作,通过上方定义的文件测试server和生成stub包。
Client / Consumer side 服务端使用:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureStubRunner(ids = {"com.example:http-server:+:stubs:8080"}, workOffline = true)
public class LoanApplicationServiceTests {
- 加号(+): 表示最大版本号
- workOffline=true:本地获取stub包
参考文档: [1]. Wiremock-testing-mocking-over-wire-stubs [2]. http://cloud.spring.io/spring-cloud-contract/ [3]. https://github.com/deliverymind/wiremock-maven-plugin [4]. http://wiremock.org/ [5]. Videos:testing microservices with WireMock [6]. http://wiremock.org/external-resources/