"Wiremock invalid response: 3"

128 Views Asked by At

I'm trying use wiremock to simulate api result and test my endpoint. But unfortunately, I got response from exception "I/O error on GET request for "http://localhost:56994": Invalid response: 3".

  1. I'm setting wiremock (it seems to work correctly (all logs working - start-stop)
@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);
    }
  1. Now I want to fake my API response by using wiremock
        //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)));

I tried with that body or with

                        .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())));

  • result is this same as above

Application works correctly but thats my impl

    @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();
    }

it throws throw new ResponseStatusException(INTERNAL_SERVER_ERROR);. before log.info("data downloaded successfully"); so there is 100% error while fetching data.

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

If you have question just ask.

I tried with different body responses, without queryParams (implementing it manually inside url)

1

There are 1 best solutions below

0
Paweł Gil On

Your returned status OK from response is from:

import static javax.security.auth.callback.ConfirmationCallback.OK;

and it's hardcoded to 3, which is not valid http status code. Instead use for example HttpStatus.OK.value(). Unfortunately rest template give you error message that is not very clear. When you change rest template for WebClient you would get error like this: org.springframework.web.reactive.function.client.WebClientRequestException: Status code '3' should be a three-digit positive integer.