有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用Mockito for HTTP客户端

我有一个存根JSON对象,但需要使用Mockito模拟以下内容:

HttpResponse response = defaultHttpClient.execute(postRequest);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuilder result = new StringBuilder();
while ((line = rd.readLine()) != null) {
    result.append(line);        
}
JSONObject jsonResponseObject = new JSONObject(result.toString()); 

我创建了以下模拟:

@Mock
    private HttpClient mockHttpClient;
    private HttpPost mockHttpPost;
    private HttpResponse mockHttpResponse;
    private HttpEntity mockHttpEntity; 
    private InputStream mockInputStream;
    private InputStreamReader mockInputStreamReader;
    private BufferedReader mockBufferedReader;

并具有以下when语句:

    Mockito.when(mockHttpClient.execute(mockHttpPost)).thenReturn(mockHttpResponse); 
    Mockito.when(mockHttpResponse.getEntity()).thenReturn(mockHttpEntity);
    Mockito.when(mockHttpEntity.getContent()).thenReturn(mockInputStream);

问:我需要创建所有这些“when”语句吗?如果需要,那么需要创建哪些其他语句才能访问存根JSON

有什么建议吗

谢谢


共 (3) 个答案

  1. # 1 楼答案

    是的,你可能需要你提到的所有when语句。 但是,您可以直接返回new ByteArrayInputStream( "{foo : 'bar'}".getBytes() ),而不是返回mockInputStream

    最后,您可以验证json响应对象是否具有值为“bar”的“foo”属性

    尽管如此,我不确定给定的方法是否值得测试——因为它所做的一切都是打开流和读取数据

  2. # 2 楼答案

    首先理解Mocking的含义

    1)为什么我们需要嘲笑

    假设我们不想调用任何原始方法,并且希望我们应该调用一个虚拟方法,而不是原始方法,那么我们应该进行模拟

    例如:

    Mockito.when(mockHttpClient.execute(mockHttpPost)).thenReturn(mockHttpResponse)
    

    这意味着无论何时调用execute(),您都将返回自己准备好的值,而不是原始的mockHttpResponse

    因此,在您的情况下,准备存根对象,如果需要,可以进行模拟。 在这里,你准备好你的回答(注意实际的,但不真实)

    mockHttpResponse.setEntity(new Entity());
    mockHttpResponse.getEntity().setContent('{yourJsonString}');
    

    所以当你的

      mockHttpClient.execute(mockHttpPost); //will be called
    

    然后它将返回您在测试方法中手动准备的响应

    当你的控制权到了

      new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
    

    然后,当调用response.getEntity().getContent()时,您将得到{yourJsonString},并让rest代码完成其功能。最后,JSON存根对象将准备就绪

    请记住,测试用例只是为开发人员提供帮助。我们可以模拟任何东西并返回任何东西或任何存根对象。我们只需编写测试用例,通过传递预期值和非预期值来检查控制流

    这将使你的工作变得容易。现在你想用这个来模拟你的BufferReader类

     BufferedReader bufferedReader = org.mockito.Mockito.mock(BufferedReader.class); 
     when(bufferedReader.readLine()).thenReturn("first line").thenReturn("second line");
    
     org.junit.Assert.when(new Client(bufferedReader).parseLine()).thenEquals(IsEqual.equalTo("1"));
    
  3. # 3 楼答案

    如果HttpClientHttpResponse是接口的话,可能需要模拟HttpClientHttpResponse(不过,根据库的不同,可以使用MockHttpClientMockHttpResponse),但你不应该模拟其他任何东西

    为什么

    模拟是在我们无法具体化的类上建立预期的输出行为,或者更确切地说,在这个特定的测试实例中,我们希望以某种方式表现的类。您希望确保从模拟HttpClient返回正确的响应,并且在调用response.getEntity()时,它会返回有意义的HttpEntity。你可以选择嘲弄,也可以不嘲弄;我个人不会,因为mock没有添加任何额外的值(除了验证是否调用了特定的方法)

    其他一切都是一个具体的实现——您应该允许其他对象与之前模拟的元素的结果进行交互,以确保它们的行为与没有模拟时的行为相同

    实际上。。。你真的不能嘲笑它们,除非你把它们传进来或以某种方式注射进去。我会极力劝阻你不要用那种方法模拟任何new的对象

    你没有具体说明你在断言什么,但我希望这是你在某种程度上的JSONObject。我会断言,您希望放入其中的内容实际上会进入JSON对象,并验证您的模拟对象是否以您期望的方式被调用和调用

    顺便说一句,您的注释@Mock不是层叠的——您必须用@Mock注释所有模拟字段,然后用@RunWith(MockitoJunitRunner.class)注释测试类,或者使用MockitoAnnotation.initMocks(this)(一个或另一个;除边缘情况外,这两个都不是必需的)。如果选择注释,不要忘记测试对象上的@InjectMocks

    最后,你的when条件做了我希望他们做的事情——这些应该没问题