Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何编写静态void方法的单元测试_Java_Unit Testing_Mockito_Httpclient_Junit5 - Fatal编程技术网

Java 如何编写静态void方法的单元测试

Java 如何编写静态void方法的单元测试,java,unit-testing,mockito,httpclient,junit5,Java,Unit Testing,Mockito,Httpclient,Junit5,我面临一个问题,我不知道如何编写静态void方法的单元测试 我现在有一个使用ApacheHttpClient的HttpHelper类。代码如下 public class HttpHelper { private static CloseableHttpClient httpClient; public static void init() { httpClient = HttpClients.custom().setSSLContext(getDummySSL(

我面临一个问题,我不知道如何编写静态void方法的单元测试

我现在有一个使用ApacheHttpClient的HttpHelper类。代码如下

public class HttpHelper {
    private static CloseableHttpClient httpClient;

    public static void init() {
        httpClient = HttpClients.custom().setSSLContext(getDummySSL()).build();
    }

    public static void closeHttpClient() throws IOException {
        httpClient.close();
    }

    private static SSLContext getDummySSL() {
        ...omit
    }

    private static void send() {
        HttpGet httpGet = new HttpGet("https://someUrl.com");

        try(CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
            if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                responseString = EntityUtils.toString(httpResponse.getEntity());
                // do something
            } else {
                throw new Exception();
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
因此,在我的主要部分中,我将调用
HttpHelper.init()
来初始化httpClient。每次我想发送请求时,我都会调用
HttpHelper.send()
。因为我不想每次都创建一个新的httpClient。最后,我将调用
HttpHelper.close()
关闭httpClient

我想知道如何测试这些无效的方法。我的概念是在测试中创建一个
CloseableHttpClient
,然后调用
HttpHelper.init()
来创建实际的一个。然后比较我的期望值和实际值是否相同。我说得对吗

由于变量和方法被声明为静态。编写单元测试有点困难。有很多帖子说,将方法设置为静态是一种不好的做法。然而,在我的示例中,我不知道如何避免将它们声明为静态并保留单个
CloseableHttpClient
实例


谢谢大家!

单实例保证主要通过单实例模式解决。单元测试的一个常见技巧是使构造函数具有受保护的可视性,您可以在其中放置用于测试的参数。这个班终于可以这样了

public class HttpHelper {
    private static HttpHelper INSTANCE = new HttpHelper();

    public static HttpHelper getInstance() {
        return INSTANCE;
    }


    private CloseableHttpClient httpClient;

    private HttpHelper() {
        SSLContext sslContext = getDummySSL();
        this(HttpClients.custom().setSSLContext(sslContext).build(), sslContext);
    }

    protected HttpHelper(CloseableHttpClient httpClient, SSLContext sslContext) {
        this.httpClient = httpClient;
    }

    public void closeHttpClient() throws IOException {
        httpClient.close();
    }

    private static SSLContext getDummySSL() {
        ...
    }

    private void send() {
        ...
    }
}

我还想将
getdummysl
重命名为
createdummysl
,但这是一个细节。

拥有一个如此静态的类是不好的,因为很难测试它。我理解你为什么想要这个,但你可以得到同样的好处:

public class HttpHelper {

    private static HttpHelper DEFAULT_INSTANCE = null;

    private CloseableHttpClient httpClient;

    public HttpHelper(CloseableHttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public static void getDeafultInstance() { // this should probably be synchronised for thread safety
        if (DEFAULT_INSTANCE == null) {
            DEFAULT_INSTANCE = httpClient = HttpClients.custom().setSSLContext(getDummySSL()).build();
        }
        return DEAFULT_INSTANCE;
    }

    private static SSLContext getDummySSL() {
        ...omit
    }

    public void closeHttpClient() throws IOException {
        httpClient.close();
    }

    private void send() {
        HttpGet httpGet = new HttpGet("https://someUrl.com");

        try(CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
            if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                responseString = EntityUtils.toString(httpResponse.getEntity());
                // do something
            } else {
                throw new Exception();
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class HttpHelperTest {

    @Test
    public testSendsRequestToSomeUrl() {
        CloseableHttpClient httpClientMock = mock();
        when(httpClient.execute(any())).thenReturn(..http_response_where_stauts_code_is_ok..)
        HttpHelper httpHelper = new HttpHelper(httpClientMock)
        httpHelper.send()
        verify(httpClient).execute(new HttpGet("https://someUrl.com"))
    }

}
HttpHelper.getDeafultInstance().send()
然后您可以这样进行单元测试:

public class HttpHelper {

    private static HttpHelper DEFAULT_INSTANCE = null;

    private CloseableHttpClient httpClient;

    public HttpHelper(CloseableHttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public static void getDeafultInstance() { // this should probably be synchronised for thread safety
        if (DEFAULT_INSTANCE == null) {
            DEFAULT_INSTANCE = httpClient = HttpClients.custom().setSSLContext(getDummySSL()).build();
        }
        return DEAFULT_INSTANCE;
    }

    private static SSLContext getDummySSL() {
        ...omit
    }

    public void closeHttpClient() throws IOException {
        httpClient.close();
    }

    private void send() {
        HttpGet httpGet = new HttpGet("https://someUrl.com");

        try(CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
            if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                responseString = EntityUtils.toString(httpResponse.getEntity());
                // do something
            } else {
                throw new Exception();
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class HttpHelperTest {

    @Test
    public testSendsRequestToSomeUrl() {
        CloseableHttpClient httpClientMock = mock();
        when(httpClient.execute(any())).thenReturn(..http_response_where_stauts_code_is_ok..)
        HttpHelper httpHelper = new HttpHelper(httpClientMock)
        httpHelper.send()
        verify(httpClient).execute(new HttpGet("https://someUrl.com"))
    }

}
HttpHelper.getDeafultInstance().send()
并在实际代码中使用它,如下所示:

public class HttpHelper {

    private static HttpHelper DEFAULT_INSTANCE = null;

    private CloseableHttpClient httpClient;

    public HttpHelper(CloseableHttpClient httpClient) {
        this.httpClient = httpClient;
    }

    public static void getDeafultInstance() { // this should probably be synchronised for thread safety
        if (DEFAULT_INSTANCE == null) {
            DEFAULT_INSTANCE = httpClient = HttpClients.custom().setSSLContext(getDummySSL()).build();
        }
        return DEAFULT_INSTANCE;
    }

    private static SSLContext getDummySSL() {
        ...omit
    }

    public void closeHttpClient() throws IOException {
        httpClient.close();
    }

    private void send() {
        HttpGet httpGet = new HttpGet("https://someUrl.com");

        try(CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
            if(httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                responseString = EntityUtils.toString(httpResponse.getEntity());
                // do something
            } else {
                throw new Exception();
            }
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class HttpHelperTest {

    @Test
    public testSendsRequestToSomeUrl() {
        CloseableHttpClient httpClientMock = mock();
        when(httpClient.execute(any())).thenReturn(..http_response_where_stauts_code_is_ok..)
        HttpHelper httpHelper = new HttpHelper(httpClientMock)
        httpHelper.send()
        verify(httpClient).execute(new HttpGet("https://someUrl.com"))
    }

}
HttpHelper.getDeafultInstance().send()
附言


如果您有某种依赖注入框架可用,那么您就可以完全摆脱静态方法。

单元测试的痛苦通常表明有代码气味。可能将
httpClient
传递到
send()
(因此
httpClient
可以轻松模拟),或者更改为非静态,并注入
httpClient
(因此
httpClient
可以轻松模拟)。您好,感谢您的回复。但如果我这样做的话。也许
httpClient
无法保留单个实例?