【问题标题】:JMockit - verify private methodJMockit - 验证私有方法
【发布时间】:2018-03-16 16:21:10
【问题描述】:

下面的方法有 3 种可能的路径: 1. 真的, 2. 错误的, 3. 例外。

为了测试它,我需要模拟 TrueException 路径的私有 getWootsWithAvailableProducts。然而,集体智慧似乎在说你不应该嘲笑私有方法。如果我不模拟私有方法并监视它以进行验证,我还能如何测试这些路径。如果这都是真的,为什么模拟私有方法这么难。如果不是真的,我错过了什么?

测试中:

  public List<Woot> findAllWoots(final boolean isBuy) throws Exception {

    final List<Woot> allWoots = wootService.findAllWoots();

    return isBuy ? getWootsWithAvailableProducts(allWoots) : allWoots;
  }

更多细节:

getWootsWithAvailableProducts 调用发出网络请求的公共服务。因此,我可以模拟实际的服务类并防止发生任何网络请求。

private List<Woot> getWootsWithAvailableProducts(List<Woot> allWoots)
    throws ServiceException {

    final String stringOfWootIds = buildStringOfCommaSeparatedIDs(allWoots);
    final List<Count> categoryIDs = wootSearchService
        .getWootIDsOfAvailableProducts(stringOfWootIds);

    return filterOnlyWootsWithAvailProducts(allCategories, categoryIDs);// also private.
}

【问题讨论】:

  • 拨打getWootsWithAvailableProducts有什么影响吗?
  • 是的,它调用了一个发出网络请求的服务。
  • 这是一个外部依赖项,应该抽象出它自己的关注点,因为它与您的代码紧密耦合并且难以单独测试。
  • 这意味着: 1. 你的网络服务依赖是隐藏的,不能被模拟,你的类与它不必要地耦合; 2. 你的课做的太多了; 3.(很可能)你的测试想法是不正确的,你的测试将与被测试的类紧密耦合。扩大您的测试范围并将测试编写为一个单元规范,而不是每个 if/else 分支的测试。
  • 该方法中只有两个路径,而不是三个。集体智慧关于不模拟私有方法是正确的,因为它们只是实现细节。一般来说,关于自动化开发人员测试,需要了解的重要一点是他们应该测试有意义的功能,仅此而已;一个好的测试只关心验证 SUT 某些部分的“业务”特性,而不关心代码片段。如果可能的话,最好不要使用嘲笑。仅在绝对必要时使用。

标签: java testing jmockit


【解决方案1】:

来自 cmets 表明 getWootsWithAvailableProducts

调用发出网络请求的服务

这是一个外部依赖项,应该抽象出它自己的关注点,因为它与您的代码紧密耦合,难以单独进行测试。

public interface WootProductsService {
    List<Woot> getWootsWithAvailableProducts(List<Woot> woots);
}

上述抽象的实现将封装网络调用,解耦原始代码,以便在单独测试方法时可以模拟抽象。

WootProductsService wootProductService; //Injected

public List<Woot> findAllWoots(final boolean isBuy) throws Exception {

    final List<Woot> allWoots = wootService.findAllWoots();

    return isBuy ? wootProductService.getWootsWithAvailableProducts(allWoots) : allWoots;
}

您现在可以控制所有依赖项,并且可以在测试所有场景时根据需要操作它们。

注意你的方法和类的关注点,因为它们会表明你的类是否做得太多。

在测试代码时遇到问题,将其视为设计不正确的标志。查看问题的原因并考虑需要应用哪些重构以使代码更加可靠。

【讨论】:

  • 我用更多细节更新了这个问题,我相信这就是你所说的。例如,服务类在被测类中使用@Injected 和它的public 进行模拟。仍然我什至看不到测试代码中的私有方法,并且将其公开似乎不正确,尽管我认为这可能是一个答案。
  • @nullsteph 您过于关注私有方法的测试。如前所述,关注公共方法并测试其行为是否符合预期。在给定可能的场景的情况下,模拟任何允许将被测方法执行到完成的依赖项。
  • 感谢您的提示。我不想在这个测试中测试这个方法,只是确认它被调用了。这个测试现在只验证两种返回类型;列表和例外
【解决方案2】:

您可以为调用此私有方法的可访问方法编写测试,然后测试所有可能的结果

另外,请确保您在模拟其他类函数和所有变量,否则在测试时执行私有函数时可能会导致问题。

所以基本上,您将像这样测试可能的场景:

私有函数返回时的公共函数

  1. 是的
  2. 异常

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多