WireMock是否支持针对指定请求运行自定义代码实现状态存储?
WireMock自定义请求处理实现说明
首先可以明确:WireMock完全支持针对特定请求运行自定义代码,核心通过ResponseDefinitionTransformer响应转换器、RequestListener请求监听器等扩展机制实现,你提到的跨请求状态维护场景可以直接通过「自定义扩展+全局内存存储」的方案实现。
具体实现步骤
1. 定义全局线程安全存储
首先用单例模式实现一个全局存储容器,用于跨请求维护条目集合,Java示例代码如下:
import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; public enum ItemDataStore { INSTANCE; // 用CopyOnWriteArrayList保证多请求并发写入的线程安全 private final List<Map<String, Object>> itemList = new CopyOnWriteArrayList<>(); public void addItem(Map<String, Object> item) { itemList.add(item); } public List<Map<String, Object>> getAllItems() { return itemList; } }这里用枚举实现单例,避免多线程环境下的实例初始化安全问题。
2. 实现POST接口自定义处理扩展
继承WireMock的
ResponseDefinitionTransformer抽象类,实现POST请求的业务逻辑:解析请求体写入全局存储,返回创建成功响应。import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; import com.github.tomakehurst.wiremock.common.FileSource; import com.github.tomakehurst.wiremock.extension.Parameters; import com.github.tomakehurst.wiremock.extension.ResponseDefinitionTransformer; import com.github.tomakehurst.wiremock.http.Request; import com.github.tomakehurst.wiremock.http.ResponseDefinition; public class PostItemTransformer extends ResponseDefinitionTransformer { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public ResponseDefinition transform(Request request, ResponseDefinition responseDefinition, FileSource fileSource, Parameters parameters) { try { // 解析POST请求的JSON body Map<String, Object> item = objectMapper.readValue(request.getBodyAsString(), new TypeReference<Map<String, Object>>() {}); // 写入全局存储 ItemDataStore.INSTANCE.addItem(item); // 构造201创建成功响应 return ResponseDefinitionBuilder.responseDefinition() .withStatus(201) .withHeader("Content-Type", "application/json") .withBody("{\"status\":\"success\",\"message\":\"条目添加完成\"}") .build(); } catch (Exception e) { // 参数异常返回400错误 return ResponseDefinitionBuilder.responseDefinition() .withStatus(400) .withHeader("Content-Type", "application/json") .withBody("{\"status\":\"fail\",\"message\":\"请求参数格式错误\"}") .build(); } } // 扩展名称,后续Stub配置时引用 @Override public String getName() { return "add-item-transformer"; } }3. 实现GET接口自定义处理扩展
同样继承
ResponseDefinitionTransformer,实现GET请求逻辑:直接读取全局存储的所有条目,序列化后返回。import com.fasterxml.jackson.databind.ObjectMapper; import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; import com.github.tomakehurst.wiremock.common.FileSource; import com.github.tomakehurst.wiremock.extension.Parameters; import com.github.tomakehurst.wiremock.extension.ResponseDefinitionTransformer; import com.github.tomakehurst.wiremock.http.Request; import com.github.tomakehurst.wiremock.http.ResponseDefinition; public class GetItemsTransformer extends ResponseDefinitionTransformer { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public ResponseDefinition transform(Request request, ResponseDefinition responseDefinition, FileSource fileSource, Parameters parameters) { try { // 读取全局存储所有条目,序列化为JSON String responseBody = objectMapper.writeValueAsString(ItemDataStore.INSTANCE.getAllItems()); return ResponseDefinitionBuilder.responseDefinition() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody(responseBody) .build(); } catch (Exception e) { return ResponseDefinitionBuilder.responseDefinition() .withStatus(500) .withHeader("Content-Type", "application/json") .withBody("{\"status\":\"fail\",\"message\":\"服务内部错误\"}") .build(); } } @Override public String getName() { return "list-items-transformer"; } }4. 注册扩展并配置Stub规则
- 如果你使用独立运行的WireMock:将上述实现的类打为jar包,放到WireMock根目录的
extensions文件夹下,启动时指定扩展类全限定名:java -jar wiremock-jre8-standalone-2.35.0.jar --extensions com.example.PostItemTransformer,com.example.GetItemsTransformer - 如果你在单元测试中使用WireMock:构造WireMockServer实例时直接传入扩展类即可。
- 最后配置两个接口的Stub规则,绑定对应转换器:
POST/items接口规则:
GET{ "request": { "method": "POST", "url": "/items" }, "response": { "transformers": ["add-item-transformer"] } }/items接口规则:{ "request": { "method": "GET", "url": "/items" }, "response": { "transformers": ["list-items-transformer"] } }
- 如果你使用独立运行的WireMock:将上述实现的类打为jar包,放到WireMock根目录的
如果需要多实例部署WireMock,只需要把全局内存存储替换为Redis、MySQL等共享存储即可实现跨实例的数据同步。
内容的提问来源于stack exchange,提问作者dotNET
相关产品推荐
相关产品推荐

