升级至Java 17后WireMock测试失败问题求助
问题分析与解决方案
背景
原技术栈:Spring Boot 2.7 + Java 8 + Jersey(JAX-RS)+ com.github.tomakehurst:wiremock-jre8:2.35.0,测试正常。
升级路径:
- 仅升级Java 17:应用运行正常,但所有WireMock测试失败,尝试多个WireMock版本(jre8 3.0.0、wiremock 3.0.0、org.wiremock 3.0.4)无效。
- 升级至Spring Boot 3(完成javax→jakarta命名空间迁移):应用恢复正常,但WireMock测试仍失败,测试了2.27.2、3.0.4、3.1.0、3.2.0、3.3.0等版本的常规/独立包均无效。
测试代码示例:
public void stubDelete(String url, int status) { WireMock.stubFor(delete(urlEqualTo(url)) .willReturn(aResponse() .withHeader("Content-Type", "application/json") .withStatus(status)) ); }
核心报错:
java.lang.IllegalStateException: Failed to load ApplicationContext ... Caused by: java.lang.ArithmeticException: long overflow
核心原因分析
long overflow 异常在该场景下的常见触发点:
- WireMock与Spring Boot 3的依赖冲突:二者底层依赖(如Netty、Jetty)版本不兼容,导致WireMock初始化时出现数值计算溢出。
- Java 17的严格溢出检查/模块权限限制:Java 17对整数溢出的检测更严格,或WireMock因模块权限不足无法访问核心类,间接引发计算异常。
- WireMock内部逻辑兼容性问题:部分版本在高Java版本下,端口随机分配、时间戳计算(如
System.nanoTime()运算)时出现溢出。
分步解决方案
1. 先定位具体溢出位置
当前报错仅显示根因,需获取完整异常堆栈跟踪,找到抛出ArithmeticException的具体类和方法,这是精准解决的关键。可通过:
- 在测试运行配置中开启完整栈打印(如Maven Surefire添加
-Dtest.stacktrace=true)。 - 查看CI/CD日志中的完整异常信息。
2. 修复WireMock与Spring Boot 3的依赖兼容性
- 统一使用WireMock 3.x的官方坐标:
org.wiremock:wiremock(3.x后不再区分jre8包),推荐版本3.3.0+(与Spring Boot 3兼容性最佳)。 - 排除冲突依赖(如Spring Boot自带的Netty、Jetty):
<dependency> <groupId>org.wiremock</groupId> <artifactId>wiremock</artifactId> <version>3.3.0</version> <scope>test</scope> <exclusions> <exclusion> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> </exclusion> <exclusion> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> </exclusion> </exclusions> </dependency>
3. 解决端口/时间计算溢出问题
若堆栈显示溢出发生在端口分配或时间计算:
- 手动指定WireMock端口,避免随机分配时的计算错误:
@BeforeEach void setUp() { WireMock.configureFor("localhost", 8089); // 固定端口 }
- 检查自定义WireMock配置(如超时),避免设置超过
Long.MAX_VALUE的数值,确保单位正确(毫秒/秒)。
4. 处理Java 17模块权限
若溢出是反射权限不足导致的间接错误:
- 在测试JVM参数中添加模块开放权限:
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED
- 或在Maven Surefire插件中配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <argLine> --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED </argLine> </configuration> </plugin>
5. 规范WireMock初始化方式
- 使用WireMock 3.x提供的
@WireMockTest注解替代手动初始化,确保与Spring上下文启动顺序兼容:
@SpringBootTest @WireMockTest(httpPort = 8089) public class IntegrationTest { // 测试逻辑 }
- 避免在Spring上下文加载前启动WireMock,防止资源冲突。
6. 验证Jersey兼容性
确保Jersey客户端版本与Spring Boot 3匹配(Spring Boot 3对应Jersey 3.x,基于Jakarta EE 9),避免客户端与WireMock交互时的潜在错误。
内容的提问来源于stack exchange,提问作者aviral
相关产品推荐
相关产品推荐

