Mocked CloseableHttpClient在测试时仍会将连接传递给真实服务器

时间:2017-06-06 17:30:44

标签: java unit-testing mocking

我尝试测试一个使用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);
    }

相关的实施

public void buy(double price) {
        String queryArgs = "command=order&amount=1" + "&price=" + String.valueOf(price); // generates query

        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost post = new HttpPost("wwww.hm.edu/projectGroup1");
        post.addHeader("Key", observer.getKey());
        try {
            post.setEntity(new ByteArrayEntity(queryArgs.getBytes("UTF-8")));
        } catch (UnsupportedEncodingException e) {
            System.out.println("Exception in run");
        }
        List<NameValuePair> params = new ArrayList<>();

        params.add(new BasicNameValuePair("command", "order"));
        params.add(new BasicNameValuePair("amount", "1"));
        params.add(new BasicNameValuePair("price", String.valueOf(price)));
        try {
            post.setEntity(new UrlEncodedFormEntity(params));
            CloseableHttpResponse response = httpClient.execute(post);
            HttpEntity entity = response.getEntity();
            Scanner in = new Scanner(entity.getContent());
            String orderNumber = "";
            while (in.hasNext()) {
                orderNumber = in.nextLine();
            }
            String[] findOrderNumber = orderNumber.split(".");
            long lastOrderNumber = -1;
            try {
                lastOrderNumber = Long.valueOf(findOrderNumber[3]);
            } catch (NumberFormatException exception) {
                System.out.println("NumberFormatException");
            } finally {
                if (lastOrderNumber != -1) {
                    observer.setOrderNumber(lastOrderNumber);
                }
            }
            in.close();
            EntityUtils.consume(entity);
            httpClient.close();
        } catch (IOException e) {
            System.out.println("Exception occured during process");
        }
    }

我尝试了几个在教程或类似问题中找到的测试代码片段,但没有成功。你能告诉我我在这里做错了什么吗?

谢谢:)

2 个答案:

答案 0 :(得分:0)

buy方法中,您使用静态方法创建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);

}

答案 1 :(得分:0)

您可以通过构造函数注入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);
}