I am trying to test the behaviour of a method in a service class. For that, I need to mock what httpClient.toBlocking().exchange( will return when called. I am trying to do this, using when - thenReturn, but I get the Error: java.lang.NullPointerException: Cannot invoke "io.micronaut.http.client.BlockingHttpClient.exchange(io.micronaut.http.HttpRequest, java.lang.Class)" because the return value of "io.micronaut.http.client.HttpClient.toBlocking()" is null
@MicronautTest public class WeatherServiceTest {
static final String HOUSE_NUM = "testNum";
static final String STREET = "testStreet";
static final String POST_CODE = "testPostCode";
static final String CITY = "testCity";
@Mock
HttpClient httpClient;
@Test
public void whenFetchingWeather() {
**when(httpClient.toBlocking().exchange(HttpRequest.GET("https://api.weatherapi.com/v1/current.json?key=XXX&q=city&aqi=no"), WeatherResponse.class))
.thenReturn(createWeatherResponse());**
WeatherService weatherService = new WeatherService();
HttpResponse<WeatherResponse> response = weatherService.fetchWeather(HOUSE_NUM, STREET, POST_CODE, CITY);
assertEquals(HttpStatus.OK, response.getStatus());
}
public static HttpResponse<WeatherResponse> createWeatherResponse() {
WeatherResponse.Condition condition = new WeatherResponse.Condition();
condition.setCode("1003");
WeatherResponse.CurrentWeather currentWeather = new WeatherResponse.CurrentWeather();
currentWeather.setCondition(condition);
currentWeather.setWind("3.6");
currentWeather.setTemperature("2.0");
WeatherResponse weatherResponse = new WeatherResponse();
weatherResponse.setCurrentWeather(currentWeather);
return HttpResponse.ok(weatherResponse);
}
}
The way to use the framework is
when(mock.method(args)).thenReturn(result)and notwhen(object.getAnotherObject().getAThirdObject().method(args)).thenReturn(result).Mockito will always call your methods, it just so happens that a Mockito mock by default doesn't do anything, until stubbed. Without stubbing, it only returns default values from methods (0 for numeric return types, empty collections, empty optionals, …, null for other objects including Strings).
So you need to stub your method
toBlocking()to return a mock itself (instead of the defaultnull), which can be stubbed subsequently. You can either do that manually or enable a setting to have your Mockito mock instances automatically answer with nested Mocks.Manual way:
Via Mockito settings:
But remember: Everytime [sic!] a mock returns a mock a fairy dies
This is stated explicitly in the Mockito docs:
Can you not use a fake implementation of HttpClient that's built for being used in tests? If not, you might want to consider wrapping the raw
HttpClientin your own class which you can then easily replace with a fake implementation or a stub in your tests.