繁体   English   中英

如何设计可用于模拟的私有/最终方法?

[英]How to design a private/final method available for mocking?

这是我必须测试的类:

public class Downloader {
  public String download(String uri) {
    HttpClient client = this.getHttpClient();
    client.setURI(uri);
    return client.get();
  }
  private HttpClient getHttpClient() {
    HttpClient client = new HttpClient();
    // + some config
    return client;
  }
}

很简单。 现在我想在getHttpClient()抛出异常时测试它的行为。 但是,我无法模仿这种方法,因为它是private 这种情况下的常见做法是什么?

我会使HTTPClient成为构建时(通过接口)设置的类的字段。 然后,您可以创建一个模拟HTTPClient,如果您愿意,可以在测试期间抛出异常,例如:

public class Downloader {
  private IHTTPClient client;

  public Downloader(IHTTPClient client) {
    this.client = client;
  }

  public String download(String uri) { 
    this.initialiseHttpClient(); 
    client.setURI(uri); 
    return client.get(); 
  } 

  private HttpClient initialiseHttpClient() { 
    // + some config 
  } 
}

然后使用生产代码中的真实HTTPClient和测试代码中的Mock调用构造函数。 您可能需要为实际代码创建HTTPClient的包装器。

如果您正在尝试测试私有方法,我认为有些不太对劲。

你应该根据合同测试你的课程。 私有方法依赖于实现,因此(从某种意义上说)它们的作用并不重要。 您应该检查您的公共方法在功能和非功能方案中是否按预期工作,并将其反映为客户端(在本例中为您的测试类)。

可能需要将某些功能替换为类以用于测试目的(例如,在破坏的JDBC连接中替换等)。在该场景中,我将研究模拟和依赖注入。

它确实听起来有点俗气,但我通常会像这样公开制作方法并添加明显的javadocs说“这种方法仅公开用于测试”。

您还可以通过在同一个包中使用xunit / mock等来使用仅包访问。

我倾向于使用像这样的简单解决方案,而不是像AOP风格的代码注入那样更复杂和难以调试的技术。

您可以使getHttpClient()受到保护并在测试中将其子类化以返回您想要的内容,因此您在测试中会有类似的内容:

public class TestableDownloader extends Downloader {

  protected HttpClient getHttpClient() {
    throw new Exception();
  }
}

这不是理想的,你最好有一个不同的设计,不要求你测试私有方法(可能使用依赖注入来提供工厂或其他东西)。

私有方法不应该进行单元测试。 您只应该对公共方法进行单元测试。 如何在内部组织公共方法与单元测试无关。 单位不等于方法。 它等于可能使用多种方法完成其工作的行为。

模拟也是一件无用的事情。 如果你必须模拟一些东西,你的方法实际上是集成函数。 你的代码需要重构才能使它只做一件事,然后一个包装器方法调用它和被模拟的对象来集成它。

单元测试听起来像你应该做的事情,但实际上是浪费你最好在编写应用程序时使用。 单元测试不能保证更好的代码质量,也许它会使它变得更糟,因为你没有在你的真实代码上花费足够的时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM