【问题标题】:Test a void method with an outgoing HTTP request使用传出 HTTP 请求测试 void 方法
【发布时间】:2017-05-26 10:20:39
【问题描述】:

我在 SO 上查找了一些较旧的问题,你们中的大多数人都说,不要测试 void 方法。

我有一个向服务器发送 HTTP 请求的方法,我认为即使该方法无效,我仍然应该测试它?如果不是,请告诉我原因,因为 dzone 的许多教程都提到您应该测试休息请求。

如果我应该测试它,请帮助我回答什么我必须测试以及如何我这样做,因为 void 不会返回任何东西。如果你看到另一个不去这里也请告诉我,我想尽可能地改进。

方法如下:

private void buy(double price) {
    final String timestamp = String.valueOf(System.currentTimeMillis());
    final String amount = String.valueOf(observer.requestedAmount);
    final String ressouce = GetValuesTypes.getRessource("user").get(observer.getRelatedUser);

    String queryArgs = "wwww.doSomething.com/" + ressouce;
    String hmac512 = HMAC512.hmac512Digest(queryArgs);

    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpPost post = new HttpPost(GetValuesTypes.getURL());
    post.addHeader("Key", GetValuesTypes.getKey());
    post.addHeader("Sign", hmac512);
    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("ressource", ressource));
    params.add(new BasicNameValuePair("rate", String.valueOf(rate)));
    params.add(new BasicNameValuePair("amount", amount));
    params.add(new BasicNameValuePair("timestamp", timestamp));
    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");
    }
}

【问题讨论】:

    标签: java rest testing


    【解决方案1】:

    您不应该直接测试private 方法。相关主题:

    但是,如果您正在测试并且需要模拟它,您可以使用PowerMock - Java 框架,它允许您对通常被认为不可测试的代码进行单元测试。代码示例:Mockito Mock Private Method Example with PowerMock

    【讨论】:

    • 就个人而言,如果我确实觉得需要测试私有方法(我尽量不这样做),我会删除“私有”修饰符并使用 com.google.common.annotations.VisibleForTesting 注释该方法
    【解决方案2】:

    一个 void 方法不会返回任何东西,但你有办法对其进行测试。

    这里主要有两种方法:

    • 一种有意义的方法:检查方法实现所产生的副作用。 方法不会什么都不做。因此,您可以检查它是否做了它应该做的事情。

    • 一种不太有意义的方法:检查方法的依赖项是否被调用,因为这些依赖项应该被调用。最后你什么都不测试。
      例如,您只需检查/断言方法 a 是使用对象 b 调用的,并且其结果在方法 c 中用作它的参数。 它是一个记录模拟行为并测试记录被调用的测试。它不可读,您可以错误地记录任何行为而在测试中看不到错误。

    在可能的情况下,单元测试应该支持输入(我想要测试的数据)和输出(我期望拥有的数据)原则。

    这就是为什么我喜欢第一种方式。

    在您的情况下,您的 void 方法生成的输出似乎是:

    if (lastOrderNumber != -1) {
        observer.setOrderNumber(lastOrderNumber);
    }
    

    在您的单元测试中,您应该有办法获取observer 字段。
    通过这种方式,您可以断言它包含您期望的订单号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-12
      • 1970-01-01
      • 2018-12-20
      • 2016-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多