Java 模拟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

我尝试测试一个使用CloseableHttpClient连接的方法。我决定使用Mockito并模拟所有相关的类和方法。但是,只要我开始测试,它就会直接进入真正的服务器,而不是被模拟的CloseableHttpClient拦截

测试

  @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);
}