我正在 Spring Boot 中测试我的服务,但我得到了
WebClientRequestException: failed to resolve 'null' after 6 queries; nested exception is java.net.UnknownHostException: failed to resolve 'null' after 6 queries.
总的来说,我对模拟和测试很陌生。我猜存根是正确完成的,但断言是错误完成的。这是我的服务:
public String changeState(String ids) {
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("ids", ids);
return webClient.post()
.uri("/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c")
.header(HttpHeaders.AUTHORIZATION, getSessionId())
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
.bodyValue(form)
.retrieve()
.bodyToMono(String.class)
.block();
}
这是我的测试,以邮递员的响应为主体:
@Test
@DisplayName("Test changeState")
void changeState() {
String body = "{\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"data\": [\n" +
" {\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"id\": \"V4600000001K001\",\n" +
" }\n" +
" ]\n" +
"}";
wireMockServer.stubFor(post(urlEqualTo("/api/v21.3/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(body))
);
String vaultIds = vaultServiceTest.changeState("V4600000001K001");
assertEquals(body, vaultIds);
}
正如我所见,断言显然是错误的,因为我断言的是整个主体而不是单个字符串。我不确定这是正确的方法还是我的测试方法整体上是错误的。
WebClientRequestException:6 次查询后未能解析“null”;
此错误消息表明,在运行测试时,正在使用
WebClient
基本 URL 创建 null
。不确定如何在实际代码中创建 WebClient
,但一种也可以在测试中实现此功能的方法是在测试类中创建一个以 localhost
作为基本 URL 的方法,以便它可以与WireMock。
例如:
@Test
@DisplayName("Test changeState")
void changeState() {
//Create and start the WireMockServer for localhost on port 8090
WireMockServer wireMockServer = new WireMockServer(8090);
wireMockServer.start();
//Create a WebClient with base URL localhost on port 8090
WebClient localhostWebClient = WebClient.builder().baseUrl("http://localhost:8090").build();
//Initialize VaultService with the localhost web client
VaultService vaultService = new VaultService(localhostWebClient);
...
要允许将
WebClient
注入 Vault 服务,请在构造函数中为 WebClient
添加参数:
public class VaultService {
private WebClient webClient;
public VaultService(WebClient webClient) {
this.webClient = webClient;
}
...
正如我所见,断言显然是错误的,因为我断言的是整个主体而不是单个字符串。
假设字段名称和数据类型匹配,并且 JSON 在语法上有效,则可以将 JSON 响应映射到 Java 对象。以下是一些可以与 JSON 响应的数据模型相匹配的 Java 对象:
VaultResponse.java:
public class VaultResponse {
private String responseStatus;
private VaultResponseData[] data;
public String getResponseStatus() {
return responseStatus;
}
public void setResponseStatus(String responseStatus) {
this.responseStatus = responseStatus;
}
public VaultResponseData[] getData() {
return data;
}
public void setData(VaultResponseData[] data) {
this.data = data;
}
}
VaultResponseData.java:
public class VaultResponseData {
private String responseStatus;
private String id;
public String getResponseStatus() {
return responseStatus;
}
public void setResponseStatus(String responseStatus) {
this.responseStatus = responseStatus;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
现在在
changeState()
方法中,响应可以映射到 VaultResponse
对象而不是 String
:
return webClient.post()
.uri("/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c")
.header(HttpHeaders.AUTHORIZATION, getSessionId())
.header(HttpHeaders.ACCEPT, PageAttributes.MediaType.APPLICATION_JSON_VALUE)
.bodyValue(form)
.retrieve()
.bodyToMono(VaultResponse.class) //Response can be mapped to an Object instead of a raw String
.block();
最后,在断言中,您可以仅对 ID 字符串而不是整个 JSON 响应正文进行断言。有几件事也必须解决:
\"id\": \"V4600000001K001\",\n"
应该变成 \"id\": \"V4600000001K001\"\n"
这是所有更改后的整个测试方法:
@Test
@DisplayName("Test changeState")
void changeState() {
//Create and start the WireMockServer for localhost on port 8090
WireMockServer wireMockServer = new WireMockServer(8090);
wireMockServer.start();
//Create a WebClient with base URL localhost on port 8090
WebClient localhostWebClient = WebClient.builder().baseUrl("http://localhost:8090").build();
//Initialize VaultService with the localhost web client
VaultService vaultService = new VaultService(localhostWebClient);
String body = "{\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"data\": [\n" +
" {\n" +
" \"responseStatus\": \"SUCCESS\",\n" +
" \"id\": \"V4600000001K001\"\n" + //Extra comma here was removed to make this valid JSON
" }\n" +
" ]\n" +
"}";
//This URL must match the URL being called in the code
wireMockServer.stubFor(post(urlEqualTo("/vobjects/ecotox_study__c/actions/Objectlifecyclestateuseraction.ecotox_study__c.study_setup_completed_state__c.change_state_to_study_contracted_useract__c"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(body))
);
VaultResponse vaultResponse = vaultService.changeState("V4600000001K001");
assertEquals("V4600000001K001", vaultResponse.getData()[0].getId());
}