我正在尝试使用wiremock来模拟api结果并测试我的端点。但不幸的是,我得到了异常的响应““http://localhost:56994”的 GET 请求上的 I/O 错误:无效响应:3”。
@SpringBootTest
@AutoConfigureMockMvc
public class WeatherControllerTest {
@Autowired
MockMvc mockMvc;
@Autowired
ObjectMapper objectMapper;
@RegisterExtension
public static WireMockExtension wireMockServer = WireMockExtension.newInstance()
.options(wireMockConfig().dynamicPort())
.build();
@DynamicPropertySource
public static void propertyOverride(DynamicPropertyRegistry registry) {
registry.add("api.weather.cityNames", () -> "Jastarnia");
registry.add("api.weather.apiKey", () -> "123");
registry.add("api.weather.baseUrl", wireMockServer::baseUrl);
}
//given
FetchWeatherResponse fetchWeatherResponse = new FetchWeatherResponse(
"Jastarnia",
Arrays.asList(
new FetchWeatherResponse.WeatherData(20.5, 10.2, "2024-01-05"),
new FetchWeatherResponse.WeatherData(18.9, 8.6, "2024-01-06")
)
);
String json = objectMapper.writeValueAsString(fetchWeatherResponse);
wireMockServer.stubFor(WireMock.get(WireMock.urlPathEqualTo("/"))
.withQueryParam("city", WireMock.equalTo("Jastarnia"))
.withQueryParam("key", WireMock.equalTo("123"))
.willReturn(aResponse()
.withStatus(OK)
.withHeader("Content-Type", APPLICATION_JSON)
.withBody(json)));
我尝试用那个身体或
.withBody("""
{
"city_name": "Warsaw",
"data": [
{
"temp": 20.5,
"wind_spd": 10.2,
"datetime": "2024-01-05"
},
{
"temp": 18.9,
"wind_spd": 8.6,
"datetime": "2024-01-06"
}
]
}""".trim())));
应用程序工作正常,但这就是我的意思
@Override
public List<FetchWeatherResponse> fetchWeather(List<String> urls) {
final HttpEntity<HttpHeaders> requestEntity = new HttpEntity<>(createHeader());
List<FetchWeatherResponse> fetchedWeathers = new LinkedList<>();
try {
for (String uri : urls) {
FetchWeatherResponse fetchedWeather = makeWeatherRequest(requestEntity, uri);
if(fetchedWeather == null) {
log.error("Response body was null.");
throw new ResponseStatusException(NO_CONTENT);
}
fetchedWeathers.add(fetchedWeather);
}
return fetchedWeathers;
} catch (ResourceAccessException e) {
log.error("Error while fetching locations: " + e.getMessage());
throw new ResponseStatusException(INTERNAL_SERVER_ERROR);
}
}
private FetchWeatherResponse makeWeatherRequest(HttpEntity<HttpHeaders> requestEntity, String url) {
ResponseEntity<FetchWeatherResponse> response = restTemplate.exchange(
url,
GET,
requestEntity,
new ParameterizedTypeReference<>() {
});
log.info("data downloaded successfully");
return response.getBody();
}
它抛出
throw new ResponseStatusException(INTERNAL_SERVER_ERROR);
。
before log.info("数据下载成功");
所以在获取数据时存在 100% 的错误。
thats my ResponseObject
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FetchWeatherResponse {
@JsonProperty("city_name")
String cityName;
@JsonProperty("data")
List<WeatherData> data;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class WeatherData {
@JsonProperty("temp")
double temperature;
@JsonProperty("wind_spd")
private double windSpd;
@JsonProperty("datetime")
private String datetime;
}
}
MvcResult response = mockMvc.perform(get("/api/best-weather?date=2024-01-05")
.contentType(APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andReturn();
And thats my full logs of wiremock during request
p.b.w.domain.weather.WeatherServiceImpl : generated url http://localhost:57135?city=Jastarnia&key=123
2024-01-06T00:28:25.285+01:00 ERROR 16300 --- [ main] p.b.w.i.fetch.FetchWeatherImpl : Error while fetching locations: I/O error on GET request for "http://localhost:57135": Invalid response: 3
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/best-weather
Parameters = {date=[2024-01-05]}
Headers = [Content-Type:"application/json;charset=UTF-8"]
Body = null
Session Attrs = {}
Handler:
Type = pl.bartoszmech.weather.application.controller.WeatherController
Method = pl.bartoszmech.weather.application.controller.WeatherController#getWeather(String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.server.ResponseStatusException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 503
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = {"message":"500 INTERNAL_SERVER_ERROR"}
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<200> but was:<503>
Expected :200
Actual :503
如果您有疑问,请提问。
我尝试了不同的正文响应,没有 queryParams(在 url 内手动实现)
您返回的状态“OK”来自:
import static javax.security.auth.callback.ConfirmationCallback.OK;
并且它被硬编码为 3,这不是有效的 http 状态代码。 相反,请使用例如
HttpStatus.OK.value()
。
不幸的是,休息模板给你的错误消息不是很清楚。
当您更改 WebClient 的其余模板时,您会收到如下错误:
org.springframework.web.reactive.function.client.WebClientRequestException:状态代码“3”应该是三位数正整数。