尝试使用 Mockito 模拟 Apache HTTP 客户端时出现问题



我是一个初学者,正在学习Mockito。我有一个 HTTP get 调用,我想模拟它。

必须测试的实用程序文件是这个。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
public class GoogleAccessor {
private HttpClient client ;
public void getGoogle() throws ClientProtocolException, IOException {
String url = "http://www.google.com/search?q=httpClient";
client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
try {
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
System.out.println(result);
} catch (Exception e) {
System.out.println(e);
}
}
}

这是我的jUnit测试

import static org.mockito.Mockito.when;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.mockito.Mock;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
public class TestTest {
@Mock
private HttpClient mClient;
@InjectMocks
private GoogleAccessor dummy;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void testAddCustomer_returnsNewCustomer() throws Exception {
when(mClient.execute(Mockito.any())).thenReturn(buildResponse(201, "OK", "{"message":"Model was stored"}"));
dummy.getGoogle();
}
BasicHttpResponse buildResponse(int statusCode, String reason, String body) {
BasicHttpResponse response = new BasicHttpResponse(
new BasicStatusLine(new ProtocolVersion("HTTP", 1, 0), statusCode, reason));
if (body != null) {
response.setEntity(new ByteArrayEntity(body.getBytes()));
}
return response;
}
}

由于mclient未启动,因此我不断收到此错误

java.lang.NullPointerException
at com.amazon.cartographertests.accessors.TestTest.testAddCustomer_returnsNewCustomer(TestTest.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
...

UPDATE1:我合并了来自@glytching的评论,并删除了setup()中的变量初始化 我合并了 @Maciej Kowalski 的评论,并使客户端成为实用程序类中的类变量

更新 2:

解析到右侧导入 -> 导入 org.mockito.Mock 后,NPE 错误已得到解决;

但是,看不到嘲笑回应的问题仍然存在

你在这里声明mClient为模拟:

@Mock
private HttpClient mClient;

但是您也为它分配了一个具体的DefaultHttpClient实例setUp()

mClient = new DefaultHttpClient();

只需从setup()中删除该行,测试中使用的mClient实例将是一个模拟。

更新:您更新的问题显示此导入:

import org.easymock.Mock;

那应该是

import org.mockito.Mock;

这条指令:MockitoAnnotations.initMocks(this);初始化任何用org.mockito.Mock注释的类成员,它不会对用org.easymock.Mock注释的类成员做任何事情,所以我怀疑mClient没有被初始化,因此没有初始化NPE。当我在本地运行您的代码时,使用正确的导入,测试成功完成,没有异常。

注意:GoogleAccessor内部也存在一个问题,您在此处getGoogle内部显式实例化HttpClient...

HttpClient client = new DefaultHttpClient();

。所以这种方法永远不会使用模拟HttpClient

如果您注释掉此行:

HttpClient client = new DefaultHttpClient();

。并将此类成员添加到GoogleAccessor

private HttpClient client;

。然后你会发现你的模拟客户端将在getGoogle()中使用。

对于背景;为了在类中使用模拟实例,您必须为测试运行程序提供某种方式将该模拟实例注入类中。在您的测试用例中,您正在使用@InjectMocks因此您指示测试运行器将模拟注入GoogleAccessor但由于没有该类型的类成员,因此测试运行器没有要分配模拟的内容。此外,即使它可以将模拟分配给某些东西,您也在getGoogle()内部声明 http 客户端,从而强制该方法的所有调用都使用DefaultHttpClient的具体实例。

您是在方法本身中创建客户端。除非创建包级方法,否则无法模拟它:

HttpClient getNewClient(){
return new DefaultHttpClient();
}

并在方法中使用它。

public void getGoogle() throws ClientProtocolException, IOException {
String url = "http://www.google.com/search?q=httpClient";
HttpClient client = getNewClient();

然后,您需要监视待测试的类,以保持被测试方法的原样,并模拟getNewClient方法以返回您想要的内容:

@Mock
private HttpClient mClient;
@InjectMocks
@Spy
private GoogleAccessor dummy;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void testAddCustomer_returnsNewCustomer() throws Exception {
doReturn(null).when(mClient).execute(Mockito.any()));
dummy.getGoogle();
}

您还需要在处理间谍时使用doReturn().when()语法而不是when().then()

相关内容

  • 没有找到相关文章

最新更新