Java 为 HTTP 客户端使用 Mockito
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20563839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Mockito for HTTP Client
提问by Global Dictator
I have a stubbed JSON OBJECT but need to mock the following using Mockito:
我有一个存根 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());
I have created the following Mocks:
我创建了以下模拟:
@Mock
private HttpClient mockHttpClient;
private HttpPost mockHttpPost;
private HttpResponse mockHttpResponse;
private HttpEntity mockHttpEntity;
private InputStream mockInputStream;
private InputStreamReader mockInputStreamReader;
private BufferedReader mockBufferedReader;
And have the following when
statements:
并有以下when
声明:
Mockito.when(mockHttpClient.execute(mockHttpPost)).thenReturn(mockHttpResponse);
Mockito.when(mockHttpResponse.getEntity()).thenReturn(mockHttpEntity);
Mockito.when(mockHttpEntity.getContent()).thenReturn(mockInputStream);
Question: Do I need to create all these 'when' statements and if yes then which other ones do I need to create to be able to get to the stubbed JSON?
问题:我是否需要创建所有这些“when”语句,如果是,那么我还需要创建哪些其他语句才能访问存根 JSON?
Any suggestions pls?
有什么建议吗?
Thanks
谢谢
回答by aquaraga
Yes, you might need all the when statements that you've mentioned.
But instead of returning the mockInputStream
, you could just return new ByteArrayInputStream( "{foo : 'bar'}".getBytes() )
是的,您可能需要您提到的所有 when 语句。但是mockInputStream
,您可以不返回,而是返回new ByteArrayInputStream( "{foo : 'bar'}".getBytes() )
Finally, you could verify that the json response object has a 'foo' property that has a value 'bar'.
最后,您可以验证 json 响应对象是否具有值为 'bar' 的 'foo' 属性。
That said, I'm not sure whether the given method is worth testing - since all it does it open streams and read data.
也就是说,我不确定给定的方法是否值得测试 - 因为它所做的一切都是打开流并读取数据。
回答by Shoaib Chikate
First understand meaning of Mocking
.
首先了解 的含义Mocking
。
1)Why we need mocking?
1)为什么我们需要嘲笑?
Suppose we don't want to call any original method and want that instead of that original method we should call a dummy method then we should go for mocking.
假设我们不想调用任何原始方法,并且希望我们应该调用一个虚拟方法而不是那个原始方法,那么我们应该进行模拟。
For e.g:
例如:
Mockito.when(mockHttpClient.execute(mockHttpPost)).thenReturn(mockHttpResponse)
This means whenever this execute()
will be called then you will return your own prepared value instead of original mockHttpResponse
.
这意味着每当execute()
调用this时,您将返回自己准备好的值而不是 original mockHttpResponse
。
So in your case prepare your stub object and mockit if you need that. Here you prepare your response(Note actual but dummy).
因此,在您的情况下,如果需要,请准备存根对象并模拟。在这里你准备你的回应(注意实际但虚拟)。
mockHttpResponse.setEntity(new Entity());
mockHttpResponse.getEntity().setContent('{yourJsonString}');
So whenever your
所以每当你
mockHttpClient.execute(mockHttpPost); //will be called
Then it will return the response that you prepared in your test method manually.
然后它将返回您在测试方法中手动准备的响应。
When your control comes to
当你的控制来到
new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
Then you will get {yourJsonString}
when response.getEntity().getContent()
is called and let rest code do its functionality. At end your JSON stubbed object will be prepared.
然后您将获得{yourJsonString}
何时response.getEntity().getContent()
被调用并让其余代码执行其功能。最后将准备好您的 JSON 存根对象。
Remember test cases are just for developers help.We can mock anything and return anything or any stub object.Just we write test case to check our control flow by passing expected and non expected values.
记住测试用例只是为了开发人员的帮助。我们可以模拟任何东西并返回任何东西或任何存根对象。只需我们编写测试用例来通过传递预期和非预期值来检查我们的控制流。
This will make your work easy.Now you want to mock your BufferReader class use this.
这将使您的工作变得轻松。现在您想使用它来模拟您的 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"));
回答by Makoto
You mighthave to mock HttpClient
and HttpResponse
, if they're interfaces (although, depending on your library, you could use MockHttpClient
or MockHttpResponse
), but you shouldn'tbe mocking anything else.
如果它们是接口,您可能必须模拟HttpClient
和HttpResponse
(尽管根据您的库,您可以使用MockHttpClient
或MockHttpResponse
),但您不应该模拟其他任何东西。
Why?
为什么?
The mock is establishing expected output behavior on classes that we cannot make concrete, or rather, classes that we want to behave in a certain way for this particular instance of a test. You want to ensure that you get the correct response back from a mock HttpClient
, and that when response.getEntity()
is called, that it gives back a meaningful HttpEntity
. You can elect to mock that out or not; I personally wouldn't, as the mock doesn't add any extra value (except to perhaps verify that a particular method was called).
模拟是在我们无法具体化的类上建立预期的输出行为,或者更确切地说,我们希望为这个特定的测试实例以某种方式表现的类。您希望确保从模拟中获得正确的响应HttpClient
,并且在response.getEntity()
被调用时返回一个有意义的HttpEntity
. 你可以选择是否嘲笑它;我个人不会,因为模拟不会添加任何额外的值(除了可能验证调用了特定方法)。
Everything else is a concrete implementation - you should be allowing the other objects to interact with the results of the previously mocked elements to ensure that they behave as they would if there were no mocks.
其他一切都是具体的实现 - 您应该允许其他对象与先前模拟的元素的结果进行交互,以确保它们的行为与没有模拟时一样。
Actually...you really can't mock those unless you pass them in or inject them in some way. I would stronglydiscourage you from attempting to mock any new
ed objects in that method.
实际上......你真的不能嘲笑那些,除非你以某种方式传递它们或注入它们。我强烈建议您不要尝试new
在该方法中模拟任何ed 对象。
You don't specify what you're asserting, but I would expect that it's your JSONObject
in some capacity. I'd assert that what you expected to be placed into it actually made it into the JSON object, and also verify that your mocked objects were called and invoked in the way you expected them to be.
你没有具体说明你在断言什么,但我希望它JSONObject
在某种程度上是你的。我会断言,您希望放入其中的内容实际上已放入 JSON 对象中,并验证您的模拟对象是否以您预期的方式被调用和调用。
Your annotation @Mock
is not cascading, by the way - you have to annotate all mocked fields with @Mock
, then either annotate the test class with @RunWith(MockitoJunitRunner.class)
, or use MockitoAnnotation.initMocks(this)
(one or the other; both aren't required except under edge cases). If you choose the annotations, don't forget @InjectMocks
on your test object.
@Mock
顺便说一下,您的注释不是级联的 - 您必须用 注释所有模拟字段@Mock
,然后用 注释测试类@RunWith(MockitoJunitRunner.class)
,或者使用MockitoAnnotation.initMocks(this)
(一个或另一个;除了在边缘情况下,两者都不是必需的)。如果您选择注释,请不要忘记@InjectMocks
您的测试对象。
Lastly, your when
conditions do what I would expect them to do - those should be fine.
最后,你的when
条件做我希望他们做的 - 那些应该没问题。