【问题标题】:Using Moq to verify execution of private methods使用 Moq 验证私有方法的执行
【发布时间】:2011-07-27 15:56:45
【问题描述】:

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

public void myPublicMethod(params) {

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

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

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

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

有什么想法吗?提前致谢。我愿意接受无法做到这一点,但我想知道一种或另一种方式。

【问题讨论】:

    标签: unit-testing mocking moq private-members


    【解决方案1】:

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

    在私有方法上构建测试会导致脆弱的测试,当您重构私有实现时(出于性能或其他原因),这些测试很容易崩溃。

    【讨论】:

    • 我不想测试实际的私有方法;我只是想验证它是否被调用。
    • 基本上,我正在努力遵守工作中的一项政策,该政策规定每次代码更改都需要相应的单元测试(这样如果单元测试稍后中断,我们就不得不真正考虑什么/为什么我们要做出改变)。我的“代码更改”是导致调用两个私有方法之一的条件逻辑。
    • 但是如果不能从外部测试行为变化​​,就意味着根本没有真正的变化。如果这只是不影响任何结果的实现细节,那么单元测试应该已经涵盖了这一点。单元测试是为了确保像这样的实现更改不会破坏任何东西。您的公司政策可能应该禁止在没有单元测试覆盖的情况下更改功能/行为,而不是添加新的单元测试。
    • A,你的澄清是有道理的。 privateMethod1 和 privateMethod2 基本上是做同一件事的两种不同方式,唯一改变的是它们“如何”工作以产生相同的结果,但结果本身是不同的。感谢您和帕特里克的帮助。
    • 不确定这个答案是否有意义。如果
    【解决方案2】:

    您的类有两个封装了一些有用行为的私有实用方法,而您正在测试的公共方法必须利用这种行为。但是,当您测试时,您不希望这些方法的正常行为,您想要替换测试行为。你在这里看到的是一个典型的依赖案例。测试时,类中的依赖可能会出现问题。

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

    private Action Behavior1;
    private Action Behavior2;
    

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

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

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

    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-11
      • 1970-01-01
      相关资源
      最近更新 更多