本地开发时如何在Micronaut中启动WireMock拦截外部服务调用
Micronaut 本地开发自动集成WireMock实现方案
Micronaut 原生提供和Spring Profile对等的环境隔离能力,本地开发启动时默认激活dev环境,你完全可以参照之前Spring里的dev环境专属配置思路实现WireMock自动启停,不需要侵入生产代码,具体步骤如下:
1. 添加开发期WireMock依赖
将WireMock标记为仅开发阶段生效的依赖,不会被打包进生产部署产物:
- 若使用Gradle(Groovy DSL),在
build.gradle中添加:
developmentOnly "com.github.tomakehurst:wiremock-jre8-standalone:2.35.1"
- 若使用Maven,在
pom.xml中添加:
<dependency> <groupId>com.github.tomakehurst</groupId> <artifactId>wiremock-jre8-standalone</artifactId> <version>2.35.1</version> <scope>development</scope> </dependency>
2. 编写dev环境专属的WireMock生命周期配置
创建一个仅在dev环境下才会被Micronaut上下文加载的配置类,绑定应用生命周期自动启停WireMock:
import com.github.tomakehurst.wiremock.WireMockServer; import io.micronaut.context.annotation.Context; import io.micronaut.context.annotation.Requires; import io.micronaut.context.event.ShutdownEvent; import io.micronaut.context.event.StartupEvent; import io.micronaut.runtime.event.annotation.EventListener; import jakarta.inject.Singleton; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; // 核心注解:仅当dev环境激活时才加载当前类 @Requires(env = "dev") @Singleton @Context // 应用启动时立即初始化当前Bean,不需要等其他Bean注入触发 public class DevWireMockConfig { private WireMockServer wireMockServer; // 固定WireMock监听端口,避免每次启动端口变动需要改配置 private static final int WIRE_MOCK_PORT = 9999; @EventListener public void onAppStartup(StartupEvent event) { wireMockServer = new WireMockServer(wireMockConfig().port(WIRE_MOCK_PORT)); wireMockServer.start(); // 加载预设的接口模拟规则 loadMockStubs(); } private void loadMockStubs() { // 示例:拦截外部用户服务的查询请求,返回预设模拟响应 stubFor(get(urlPathEqualTo("/api/external/users/1")) .willReturn(okJson(""" { "id": 1, "username": "mock_user", "email": "mock@local.dev" } """)) ); // 其他外部服务的模拟规则按相同格式追加即可 } @EventListener public void onAppShutdown(ShutdownEvent event) { if (wireMockServer != null && wireMockServer.isRunning()) { wireMockServer.stop(); } } }
3. 配置dev环境下的外部服务指向
在src/main/resources/application-dev.yml中配置所有外部服务的调用地址为本地WireMock地址,这个配置文件仅在dev环境激活时会被加载,完全不会影响其他环境:
micronaut: http: services: # 对应你代码中@Client("user-service")声明的外部服务客户端 user-service: urls: - http://localhost:9999 # 其他需要被WireMock拦截的外部服务都可以指向同一个端口 order-service: urls: - http://localhost:9999
可选优化项
- 如果模拟规则较多,可以把WireMock原生支持的JSON格式stub文件放到
src/main/resources/wiremock/mappings目录下,启动WireMock时直接加载目录内所有规则,不用把stub逻辑硬编码在Java代码中,初始化代码修改为:
wireMockServer = new WireMockServer(wireMockConfig() .port(WIRE_MOCK_PORT) .usingFilesUnderClasspath("wiremock") );
- 如果不想固定端口,可以配置WireMock启动时选择随机可用端口,再通过Micronaut的动态属性注入机制把随机端口写入服务地址配置,不过本地开发场景下固定端口调试成本更低。
注意:不要把上述WireMock配置类放到测试代码目录,要保留在main源码路径下,靠@Requires(env = "dev")注解控制加载范围,这样不管是直接在IDE里运行主启动类,还是用./gradlew run/mvn mn:run命令启动应用,都会自动拉起WireMock,生产环境部署时不会激活dev环境,相关代码和依赖都不会生效。
内容的提问来源于stack exchange,提问作者user1555190
相关产品推荐
相关产品推荐

