我正在尝试测试服务类中方法的行为。为此,我需要模拟 httpClient.toBlocking().exchange( 调用时将返回的内容。 我正在尝试使用when - thenReturn 来执行此操作,但出现错误: java.lang.NullPointerException:无法调用“io.micronaut.http.client.BlockingHttpClient.exchange(io.micronaut.http.HttpRequest,java.lang.Class)”,因为“io.micronaut.http.client的返回值。 HttpClient.toBlocking()”为空
@MicronautTest 公共类 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);
}
}
使用框架的方式是
when(object.method(args)).thenReturn(result)
而不是when(object.getAnotherObject().getAThirdObject().method(args)).thenReturn(result)
。
Mockito 会总是调用你的方法,它只是发生,所以默认情况下 Mockito 模拟不会执行任何操作,直到被存根。
因此,您需要存根您的方法
toBlocking()
以返回模拟本身,随后可以对其进行存根。您可以手动执行此操作,也可以启用设置以使您的 Mockito 模拟实例自动使用嵌套模拟进行应答。
手动方式:
final BlockingHttpClient blockingClientMock = mock(BlockingHttpClient.class);
when(httpClient.toBlocking()).thenReturn(blockingClientMock);
when(blockingMock.exchange(HttpRequest.GET("https://api.weatherapi.com/v1/current.json?key=XXX&q=city&aqi=no"), WeatherResponse.class))
.thenReturn(createWeatherResponse());
通过 Mockito 设置:
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private HttpClient httpClient;
when(httpClient.toBlocking().exchange(HttpRequest.GET("https://api.weatherapi.com/v1/current.json?key=XXX&q=city&aqi=no"), WeatherResponse.class))
.thenReturn(createWeatherResponse());
这在 Mockito 文档中明确说明:
警告:常规的干净代码很少需要此功能!将其留给遗留代码。模拟模拟以返回模拟,返回模拟,(...),返回一些有意义的暗示违反德米特法则或模拟值对象(众所周知的反模式)。
您不能使用为测试而构建的 HttpClient 的虚假实现吗?如果没有,您可能需要考虑将原始
HttpClient
包装在您自己的类中,然后您可以在测试中轻松地用假实现或存根替换它。