微信 API Mock Server 的 WireMock 规则编写与契约测试集成
·
微信 API Mock Server 的 WireMock 规则编写与契约测试集成
在开发对接企业微信或微信支付等服务时,频繁调用真实 API 会受限于配额、网络延迟及环境依赖。使用 WireMock 构建本地 Mock Server 可有效解耦外部依赖,提升单元测试稳定性与执行速度。本文展示如何基于 WireMock 编写微信 API 的 Mock 规则,并将其集成到基于 Spring Boot 的契约测试流程中,确保接口契约一致性。
WireMock 基础配置与启动
首先引入依赖(pom.xml):
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<version>2.35.0</version>
<scope>test</scope>
</dependency>
在测试类中启动 WireMock 服务,模拟微信域名 qyapi.weixin.qq.com:
package wlkankan.cn.test.mock;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
public abstract class BaseWeComMockTest {
protected WireMockServer wireMockServer;
@BeforeEach
void startMockServer() {
wireMockServer = new WireMockServer(WireMockConfiguration.options()
.port(8089)
.bindAddress("127.0.0.1")
.httpsPort(8443)
.usingFilesUnderClasspath("wiremock/wechat"));
wireMockServer.start();
// 动态替换微信 API 地址为 localhost:8089
System.setProperty("wecom.api.base-url", "http://localhost:8089");
}
@AfterEach
void stopMockServer() {
if (wireMockServer != null) {
wireMockServer.stop();
}
}
}

编写微信获取 access_token 的 Mock 规则
微信获取 token 的请求为:
POST https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET
在 src/test/resources/wiremock/wechat/mappings/gettoken.json 中定义响应:
{
"request": {
"method": "GET",
"urlPath": "/cgi-bin/gettoken",
"queryParameters": {
"corpid": { "equalTo": "wx1234567890abcdef" },
"corpsecret": { "equalTo": "secret_9876543210fedcba" }
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json; charset=utf-8"
},
"jsonBody": {
"errcode": 0,
"errmsg": "ok",
"access_token": "mock_access_token_abc123",
"expires_in": 7200
}
}
}
也可通过 Java API 动态注册:
package wlkankan.cn.test.mock;
import com.github.tomakehurst.wiremock.client.WireMock;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
public class WeComTokenMockRule {
public static void stubGetTokenSuccess(WireMockServer server) {
server.stubFor(get(urlPathEqualTo("/cgi-bin/gettoken"))
.withQueryParam("corpid", equalTo("wx1234567890abcdef"))
.withQueryParam("corpsecret", equalTo("secret_9876543210fedcba"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json; charset=utf-8")
.withJsonBody(org.skyscreamer.jsonassert.JSONParser.parseJSON(
"{ \"errcode\": 0, \"errmsg\": \"ok\", \"access_token\": \"mock_token_xyz\", \"expires_in\": 7200 }"
))
)
);
}
}
Mock 外部联系人列表接口
微信获取外部联系人列表的请求:
GET https://qyapi.weixin.qq.com/cgi-bin/externalcontact/list?access_token=TOKEN&userid=USERID
Java 动态 Stub 示例:
package wlkankan.cn.test.mock;
import com.github.tomakehurst.wiremock.WireMockServer;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
public class WeComContactMockRule {
public static void stubListExternalContacts(WireMockServer server) {
server.stubFor(get(urlPathEqualTo("/cgi-bin/externalcontact/list"))
.withQueryParam("access_token", equalTo("mock_token_xyz"))
.withQueryParam("userid", equalTo("zhangsan"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json; charset=utf-8")
.withBodyFile("responses/externalcontact_list_success.json")
)
);
}
}
对应的 src/test/resources/wiremock/wechat/__files/responses/externalcontact_list_success.json 内容:
{
"errcode": 0,
"errmsg": "ok",
"external_userid": ["woAJ2GCAAAXtWyujaWJHDDGi0mACH71w", "woAJ2GCAAAXtWyujaWJHDDGi0mACH71x"]
}
集成到 Spring Boot 测试与契约验证
在 wlkankan.cn.service 包中编写服务类:
package wlkankan.cn.service;
import org.springframework.web.client.RestTemplate;
public class WeComContactService {
private final RestTemplate restTemplate;
private final String baseUrl;
public WeComContactService(RestTemplate restTemplate, String baseUrl) {
this.restTemplate = restTemplate;
this.baseUrl = baseUrl;
}
public ExternalContactListResponse listContacts(String accessToken, String userId) {
String url = baseUrl + "/cgi-bin/externalcontact/list?access_token=" + accessToken + "&userid=" + userId;
return restTemplate.getForObject(url, ExternalContactListResponse.class);
}
}
编写契约测试用例:
package wlkankan.cn.test.contract;
import wlkankan.cn.test.mock.BaseWeComMockTest;
import wlkankan.cn.test.mock.WeComTokenMockRule;
import wlkankan.cn.test.mock.WeComContactMockRule;
import wlkankan.cn.service.WeComContactService;
import org.junit.jupiter.api.Test;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
public class WeComContactServiceContractTest extends BaseWeComMockTest {
@Test
void should_return_external_contact_list_when_token_valid() {
// Given
WeComTokenMockRule.stubGetTokenSuccess(wireMockServer);
WeComContactMockRule.stubListExternalContacts(wireMockServer);
WeComContactService service = new WeComContactService(new RestTemplate(), "http://localhost:8089");
// When
var response = service.listContacts("mock_token_xyz", "zhangsan");
// Then
assertThat(response.getErrcode()).isEqualTo(0);
assertThat(response.getExternalUserid()).hasSize(2);
assertThat(response.getExternalUserid().get(0))
.isEqualTo("woAJ2GCAAAXtWyujaWJHDDGi0mACH71w");
}
}
自动化契约生成与验证
可结合 Pact 或 Spring Cloud Contract 实现双向契约管理。但即使仅使用 WireMock,也可通过以下方式保障契约一致性:
- 将
.json映射文件纳入版本控制; - 在 CI 流程中运行所有 Mock 测试;
- 定期从真实微信 API 抓包更新响应样本。
通过 WireMock 精准模拟微信 API 行为,团队可在无网络、无权限环境下完成高覆盖率的集成测试,显著提升交付效率与系统健壮性。
更多推荐



所有评论(0)