使用 Mockito (Java) 进行 Micronaut HttpClient 测试

问题描述 投票:0回答:1

我正在尝试测试服务类中方法的行为。为此,我需要模拟 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);
}

}

java mockito junit5 micronaut micronaut-client
1个回答
1
投票

使用框架的方式是

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
包装在您自己的类中,然后您可以在测试中轻松地用假实现或存根替换它。

© www.soinside.com 2019 - 2024. All rights reserved.