使用Spring Boot + WireMock时出现NoHttpResponseException
事件
我进行了商用Spring Boot应用的改修。
在该应用中,有一个部分使用了RestTemplate来调用其他相关联的系统的REST API。我使用WireMock构建了一个模拟服务器来进行包含这部分的单元测试。
根据改修进行添加了一些测试后,现有的测试突然开始抛出NoHttpResponseException: [server] failed to respond等异常并失败了。
由于在单独执行测试时能够通过,而在连续执行测试时失败,说明问题不在于测试本身而是其他原因。因此,开始调查。
原因
据说当使用HttpURLConnection作为访问WireMock的App的Http Client时会出现一个bug。
https://github.com/tomakehurst/wiremock/issues/97
Spring的RestTemplate在内部也使用了HttpURLConnection,所以涉及到这个问题。
解决办法
使用Spring Cloud Contract WireMock。
https://github.com/tomakehurst/wiremock/issues/97
由于该问题已经提供了多种解决方案,您可以选择其中之一来采用。
以下是一种初步的选择标准。
-
- Spring Bootのバージョンを上げる or HttpClientを変える
-
- 商用で動いているAppなので、テストのために構成変更は基本NG→✕
-
- HttpClientのconnection reuseを無効化
-
- 設定場所が分からないし、Appの動作に影響出そう→✕
-
- spring-cloud-contract-wiremockの利用
- テストのライブラリ変更だけで完結→○
spring-cloud-contract-wiremock之所以取这个名字,是因为在内部使用了WireMock,因此只需最小限度更改测试代码。
具体来说,只需更改服务器配置语法,然后指定现有测试资源目录即可。
有关详细使用方法,请参考官方文档。
public class ExampleUnitTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(8080);
....
@AutoConfigureWireMock(port = 8080, stubs = "classpath*:/META-INF/**/mappings/**/*.json")
public class ExampleUnitTest {
....
如上所述,我只需将我的情况下已指定为存根(stubs)的测试资源路径处理好,现有的测试代码就可以如原样通过。