使用Mockito创建HTTP响应作为返回值

4

我是Mockito测试的新手,并正在测试一个GET请求。

我已经模拟了调用,但现在我需要返回HttpResponse<Cars[]>,因为这些值稍后在for循环中使用。

我该如何创建一个虚拟的HttpResponse,其中的主体包含Car对象数组。

使用GET请求的方法位于CarProvider类中:

public HttpResponse<Cars[]> getCars(String carId, String carname) {
    return Unirest.get(endpointUrl)
          .header("Accept", MediaType.APPLICATION_JSON)
          .queryString("carId",cardId)
          .queryString("carname",carname)
          .asObject(Cars[].class);
}

以下方法中在另一个类CarsUsers中使用:

public List<Cars> getCars(String carId, String carname) {
  HttpResponse<Cars[]> response = carProvider.getCars(carId, carname);
  for(Cars car: response.getBody){
     //use car and do something
}

我的测试方法如下:

public class TestClass {
    @Mock
    HttpResponse<Cars[]> httpresponse;
    @Mock
    CarsProvider carsProvider;

    @Mock
    CarsUser carsUser;

    @Test
    public void getCarsTest(){
     Mockito.when(carsUser.getCars(Matchers.anyString(), 
     Matchers.anyString())).thenReturn(getDummyCarsList());

     Mockito.when(carsProvider.getCars(Matchers.anyString(), 
     Matchers.anyString())).thenReturn(httpResponse);

     }

    private List<Cars> getDummyCarsList(){
    //create a dummy list of cars
    }
}

我在 for(Cars car: response.getBody){} 这一行代码中遇到了 NullPointerException 异常。

我猜测是因为 body 没有任何值,所以才会抛出异常。

感激任何帮助或建议。

谢谢


也许展示一下你想要测试的方法。 - flakes
2
能否更新您的问题,以展示一些样本代码?您问题的答案可能像这样:HttpResponse response = Mockito.mock(HttpResponse.class); Mockito.when(response.xxx).thenReturn(arrayOfCars);但如果没有更多详细信息,很难确定您应该怎么做。请考虑发布一个 MCVE - glytching
样例代码可能非常有帮助。 - Keshava
已更新问题。 - pgman
准备一个适当的主体来创建你的模拟,这个主体本身也可以是一个模拟:when(response.getBody()).thenReturn(something) - Andy Brown
1个回答

10
你真的需要让CarProvider返回HttpResponse<Car[]>吗?
感觉底层通信的一个方面(HttpResponse)可能会泄漏。如果CarProvider的目的是提供汽车,那么它应该相应地进行类型定义。
因此,如果你将CarProvider声明如下...
public class CarProvider {
    // should perhaps consider List<Car> instead of Car[] here ...
    public Cars[] getCars(String carId, String carname) {
        HttpResponse<Car{}> response = Unirest.get(endpointUrl)
          .header("Accept", MediaType.APPLICATION_JSON)
          .queryString("carId",cardId)
          .queryString("carname",carname);

        return deserialise(response.getBody());
    }

    private Car[] deserialise(ResponseBody body) {
        // read the body and deserialise to Car[] 
    }
}

如果你使用了TestNG框架,那么你的测试方法会更加简单明了:
@Test
public void getCarsTest(){
    Mockito.when(carsUser.getCars(anyString(), anyString())).thenReturn(getDummyCarsList());

    // ...
}

private Cars[] getDummyCarsList(){
    return new Car{} {new Car(...), new Car(...)};
}

然而,如果真的无法避免且你必须模拟 HttpResponse<Car[]> ,那么可以按照以下方式进行:

HttpResponse<Car[]> mockedResponse = Mockito.mock(HttpResponse.class);
Mockito.when(mockedResponse.getCode()).thenReturn(200);
Mockito.when(mockedResponse.getBody()).thenReturn(someSerialisedFormOfYourCarArray);

Mockito.when(carsUser.getCars(anyString(), anyString())).thenReturn(mockedResponse);

谢谢您的回复,我会尝试这个。 - pgman
1
顺便说一句,我刚刚更新了答案,向您展示如何模拟HttpResponse,以防您真的无法重新声明CarProvider - glytching
谢谢。这帮助我意识到,我甚至需要模拟“汽车”数组。 - pgman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接