Java 模拟CloseableHttpClient在测试时仍将连接传递到真实服务器
我尝试测试一个使用CloseableHttpClient连接的方法。我决定使用Mockito并模拟所有相关的类和方法。但是,只要我开始测试,它就会直接进入真正的服务器,而不是被模拟的CloseableHttpClient拦截 测试Java 模拟CloseableHttpClient在测试时仍将连接传递到真实服务器,java,unit-testing,mocking,Java,Unit Testing,Mocking,我尝试测试一个使用CloseableHttpClient连接的方法。我决定使用Mockito并模拟所有相关的类和方法。但是,只要我开始测试,它就会直接进入真正的服务器,而不是被模拟的CloseableHttpClient拦截 测试 @Test public void testBid() throws IOException { //given: HttpGet httpGet = mock(HttpGet.class); HttpRes
@Test
public void testBid() throws IOException {
//given:
HttpGet httpGet = mock(HttpGet.class);
HttpResponse httpResponse = mock(HttpResponse.class);
StatusLine statusLine = mock(StatusLine.class);
ObserverImp observer = mock(ObserverImp.class);
CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient.class);
CloseableHttpResponse closeableHttpResponse = mock(CloseableHttpResponse.class);
//and:
when(statusLine.getStatusCode()).thenReturn(200);
when(httpResponse.getStatusLine()).thenReturn(statusLine);
when(closeableHttpClient.execute(httpGet)).thenReturn(closeableHttpResponse);
when(observer.getKey()).thenReturn("##213");
Buy buy = new Buy(observer);
buy.bid(14455);
}
以及相关的实施
我尝试了一些在教程或类似问题中找到的测试代码片段,但没有成功。你能告诉我我做错了什么吗
谢谢:在您的购买方法中,您正在使用静态方法创建httpClient,如下所示
CloseableHttpClient httpClient = HttpClients.createDefault();
现在,每次您调用buy时,都会创建真正的http客户机,并调用真正的服务。相反,您应该从测试代码中将httpClient作为依赖项作为模拟httpClient传递,如
public void buy(double price, HttpClient httpClient) {
..
}
在测试中:
public void test() {
HttpClient httpClient = mock(HttpClient.class)
// mock the behavour
// SUT
buy(..., httpClient);
}
您可以通过构造函数注入CloseableHttpClient httpClient:
public class Buy {
private ObserverImp observer;
private CloseableHttpClient httpClient;
public Buy (ObserverImp observer, CloseableHttpClient httpClient) {
this.observer = observer;
this.httpClient = httpClient;
}
public void buy(double price) {
...
// Comment or remove the line below and use the injected instead...
// CloseableHttpClient httpClient = HttpClients.createDefault();
...
}
}
要测试它,请执行以下操作:
@Test
public void testBid() throws IOException {
//given:
HttpGet httpGet = mock(HttpGet.class);
HttpResponse httpResponse = mock(HttpResponse.class);
StatusLine statusLine = mock(StatusLine.class);
ObserverImp observer = mock(ObserverImp.class);
CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient.class);
CloseableHttpResponse closeableHttpResponse = mock(CloseableHttpResponse.class);
//and:
when(statusLine.getStatusCode()).thenReturn(200);
when(httpResponse.getStatusLine()).thenReturn(statusLine);
when(closeableHttpClient.execute(httpGet)).thenReturn(closeableHttpResponse);
when(observer.getKey()).thenReturn("##213");
Buy buy = new Buy(observer, closeableHttpClient);
buy.bid(14455);
}
谢谢你的回答!我应该仅仅为了测试而更改CTOR,还是应该进行一般性更改?或者我可以创建第二个CTOR重载好的程序员的方式是什么:?我刚刚看到我必须对HttpPost执行同样的操作,然后更正?不客气。没有正确的答案。但是您可以重载构造函数,定义一个只接收OberserverImp实例的构造函数,比如BuyObserverImp obs{thisobs,HttpClients.createDefault;}。通常,您只调用一个参数构造函数。要进行测试,请调用两个参数构造函数。明白我的意思了吗?是的:所以我的问题的目标是,如果仅仅为了测试目的而创建一个CTOR是一个好的设计决策,那么好的做法是,在您的例子中,反转http客户端dep是一个好的做法,这样,在将来,如果您必须使用SecureHttpClient,那么您就不必修改“购买”代码。还有一件事,为UT添加构造函数是可以的,只要您通过使包私有化来隐藏它们。
@Test
public void testBid() throws IOException {
//given:
HttpGet httpGet = mock(HttpGet.class);
HttpResponse httpResponse = mock(HttpResponse.class);
StatusLine statusLine = mock(StatusLine.class);
ObserverImp observer = mock(ObserverImp.class);
CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient.class);
CloseableHttpResponse closeableHttpResponse = mock(CloseableHttpResponse.class);
//and:
when(statusLine.getStatusCode()).thenReturn(200);
when(httpResponse.getStatusLine()).thenReturn(statusLine);
when(closeableHttpClient.execute(httpGet)).thenReturn(closeableHttpResponse);
when(observer.getKey()).thenReturn("##213");
Buy buy = new Buy(observer, closeableHttpClient);
buy.bid(14455);
}