使用Moq验证私有方法的执行

时间:2011-07-27 15:56:45

标签: unit-testing mocking moq private-members

我想测试以下逻辑(这显然是我方法的精简版):

public void myPublicMethod(params) {

    if(some_condition)
        privateMethod1();
    else
        privateMethod2();
} 

我已经模拟了方法中的所有其他依赖项,并且我已经设置了它,以便我可以保证some_condition为true。我想要做的是验证我的privateMethod1()只被调用一次,并且根本不调用privateMethod2()。这可能与Moq有关吗?

以下是有关该问题的一些说明:

  • privateMethod1()和privateMethod2()与myPublicMethod位于同一个类中,因此我无法为此类创建模拟对象。
  • privateMethod1 / 2的主体包含来自包含这些和myPublicMethod的类的许多依赖项,因此将privateMethod1 / 2分解为它们自己的帮助程序类将非常耗时

有什么想法?提前致谢。我愿意接受这不可能做到,但我想知道这种或那种方式。

2 个答案:

答案 0 :(得分:15)

不要测试私有方法。它们是该类的私有实现细节。您应该只测试执行公共方法的结果。只要您的结果按预期结果出来,您就不应该关心如何获得结果。

对私有方法进行构建测试将导致在重构私有实现时(由于性能或其他原因)容易破解的脆弱测试。

答案 1 :(得分:4)

您的类有两个私有实用程序方法,它们封装了一些有用的行为,您正在测试的公共方法必须使用此行为。但是,在测试时,您不希望这些方法的正常行为,您想要替换测试行为。你在这里有一个经典的依赖案例。在测试时,课堂上的家属可能会出现问题。

因此,解决方案与外部依赖项的解决方案相同:使用一种或另一种依赖项注入来从要实现该行为的私有方法中删除要测试的方法。 例如,可以声明两个私有委托来表示行为:

private Action Behavior1;
private Action Behavior2;

在类构造函数中,实现了正常的行为:

public Foo (...)
{
    Behavior1 = privateMethod1;
    Behavior2 = privateMethod2;
...
}

在public方法中调用委托而不是实际方法:

public void myPublicMethod(params) {
    if(some_condition)
        Behavior1();
    else
        Behavior2();
} 

通过这样做,方法之间的绝对依赖性已被消除,所以现在它是可测试的。

现在,在测试中,在创建测试对象实例之后,您可以覆盖依赖行为:

Foo_Accessor testMe = new Foo_Accessor();

bool wasCalled1 = false

testMe.Behavior1 = new Action(() => wasCalled1 = true);

...

Assert.IsTrue(wasCalled1);