【问题描述】:

我对以下方法进行单元测试时遇到了一些问题。

public List<GetSupplyChainResponse> getSupplyChains(){
    List<GetSupplyChainsResponse> response = new ArrayList<>();
    supplyChainRepository.findSupplyChainsWithCompound().forEach(result
            -> response.add(getGetSupplyChainSimpleResponse(result)));

    return response;
}

getGetSupplyChainSimpleResponse()是与getSupplyChains()同类的私有方法

因此有没有可能定义返回值,或者您有任何其他想法我可以如何测试方法 getSupplyChains()

【问题讨论】:

  • 你可以使用反射。看到这个stackoverflow.com/questions/11282265/…
  • 您遇到了什么问题?你有任何错误吗?也许您还想显示 getGetSupplyChainSimpleResponse() 方法,以便我们可以看到其中发生了什么。
  • 您测试方法 getSupplyChains() 的方法与没有调用 private 方法的 lambda 表达式的测试方法完全相同。

标签: java unit-testing testing lambda private


【解答1】:

你可能想多了。您要测试的方法 (getSupplyChains) 使用调用私有方法的 lambda 这一事实无关紧要:它们只是实现细节。

您的单元测试是您作为客户端与之交互的类的一部分,即它的接口。您通常使用一些参数调用公共方法(在这种情况下没有参数),您会得到一些返回值,这就是您在单元测试中验证的内容。如果你的公共方法使用了一些私有方法,它也会被测试

这里的问题是,您从 getSupplyChains 获得的响应显然取决于 supplyChainRepository.findSupplyChainsWithCompound() 返回的内容。在这种情况下,您所做的是模拟该依赖项 (supplyChainRepository):创建 SupplyChainRepository 的模拟实例,告诉它如何表现,然后将其传递给类,例如通过构造函数。

您可以自己编写模拟,也可以依靠模拟框架来完成繁重的工作,例如 Mockito

我绝对建议不要对私有方法进行单元测试(它会导致脆弱的测试),或者增加这些方法的可见性(也就是为了测试而牺牲你的设计)。

【问题讨论】:

    【解答2】:

    这是一个经常讨论的问题,有些人更喜欢使用 Janos Binder 推荐的反射 (How to call a private method from outside a java class),有些人可以接受我们需要模拟的方法的可见性为了可测试性而增加的事实。< /p>

    这个问题在这里得到了很好的讨论:How do I test a class that has private methods, fields or inner classes?。从答案和广泛的讨论中可以看出,这个话题相当复杂,开发者分成不同的派别,使用不同的解决方案。

    我建议您删除 private 访问修饰符并将方法包设为私有(使用默认可见性)。常见的习惯是将测试类与测试类放在同一个包中(但不在同一个文件夹中!)。

    这将允许您:

    1. 测试 getGetSupplyChainSimpleResponse() 方法本身,无论如何你都应该这样做。

    2. 为了测试 getSupplyChains() 模拟其行为。这你将实现例如通过使用 Mockito 框架及其@Spy functionality

    对于那些认为这是“为了测试而牺牲你的设计”的人,我会回答 如果你有需要模拟和/或测试的私有方法,那么无论如何设计都不理想所以将可见性更改为包私有并不意味着太大的恶化。明确的解决方案(从面向对象设计的角度来看)是将此类私有方法的行为委托给单独的类。然而,在现实生活中,有时这只是矫枉过正。

    【问题讨论】: