首页 > 解决方案 > 如何在没有单元测试私有方法的情况下进行单元测试?

问题描述

我在一个大致看起来像这样的方法中有相当多的代码

public void A(boolean f1, boolean f2, boolean f3, int var1, int var2, String var3) {
    if(f1){
        doSomething(var1)
    } else if(f2) {
        doSomethingElse(var1);
        doSomethingMore(var3);
    } else if(f3) {
        doSomethingDifferent();
        doSomethingElse(var2);
        doSomethingDifferentAgain();
    }
}

private void doSomething(int var) { ... }
private void doSomethingElse(int var) { ... }
private void doSomethingMore(String var) { ... }
private void doSomethingDifferent() { ... }
private void doSomethingDifferentAgain() { ... }

现在,如果我将这些方法都定义为私有,我应该如何测试它们?每个方法中的逻辑都是相当自封闭的,但是仅测试公共方法将需要在测试中进行更多的“处理”,而不是仅测试该方法。

测试这样的代码的推荐方法是什么?

标签: unit-testingtestingjunit

解决方案


你应该读帕纳斯 1971

测试这样的代码的推荐方法是什么?

TDD 的基本主题是我们不测试这样的代码。相反,我们用一种更重视可测试性的设计来替换像这样的设计。

声称是,当您优先考虑可测试性时,您会得到 Parnas 所说的那种模块;因此,未来的更改更容易安全地集成到您的代码库中,因此您能够以稳定的速度交付业务价值。

对于 TDD 从业者来说,复杂的测试——尤其是设置复杂的测试(“Given ...”)——是一种症状。通常原因是我们想要测量的事物与其他不相关的细节之间存在过多的耦合。响应是重新设计代码以减少耦合。

所以我们可能会从

private void somethingCoupledToTheWorld(args...) {
    // Complicated things here
}

class DecoupledThing {
    public nowEasyToTest(args...) {
        // Complicated things here
    }
}

private DecoupledThing that = DecoupledThing()

private void somethingCoupledToTheWorld(args...) {
    that.nowEasyToTest(args)
}

由此产生的设计往往有更多的模块;尤其是 (a) 更多的模块做好一件事 (SRP),以及 (b) 更多的模块除了将工作委派给其他模块之外似乎没有做太多的事情。

表达相同想法的另一种方式:我们调整我们的设计,使高风险代码位于易于测试的模块中。

一些好消息:如果你已经获得了 A 的测试,你仍然可以使用它们。它们有助于确保代码的行为不会在您将设计重构为支持更集中测试的设计时发生变化。


推荐阅读