使方法"内部"去除依赖性(用于单元测试) - 一个好的做法?有更好的方法吗?

Red*_*zon 5 c# unit-testing

我有一个课程如下.

public class MyClass  
{  
    public MyMethod()  
    {  
      int x = CalculateSomething();  
    }

   private int CalculateSomething()  
   {  
      // Do something and return an int    
      return 100;  
   }  
}  
Run Code Online (Sandbox Code Playgroud)

为了进行单元测试,我添加[assembly: InternalsVisibleTo("MyTests")]了私有方法并将其更改为内部虚拟方法.在单元测试项目中,我创建了一个类MockMyClass并创建了如下的私有方法.

public class MockMyClass : MyClass  
{  
   public bool MadeHappyNoise {get; set;}
   internal override int CalculateSomething()  
   {  
      MadeHappyNoise = true;  
      return base.CalculateSomething();  
   }  
}
Run Code Online (Sandbox Code Playgroud)

单元测试现在如下

[TestMethod()]
public void WasCalculateSomethingCalledOK()  
{  
   MockMyClass mk = new MockMyClass();
   mk.MyMethod();  
   Assert.IsTrue(mk.MadeHappyNoise, "Oops...CalculateSomething not called...");  
}  
Run Code Online (Sandbox Code Playgroud)

几个问题:这是删除依赖关系的好方法吗?我个人不喜欢将方法从私有更改为内部但没有选项(除了使用Reflection之外).此外,驻留在生产代码中的属性InternalsVisibleTo("MyTests")也不好.有人能指出我更好的解决方案吗?谢谢.

TTo*_*oni 1

唔。我对该代码有一些问题,但我们一次会解决一个问题。

  1. 为什么要测试 MyMethod 是否调用CalculateSomething?这是一个可能会改变的实现细节(如果它明天调用CalculateSomething2,但除此之外仍然执行它应该执行的操作怎么办?)。如果您想测试 MyMethod 的代码结构,请进行代码审查,而不是单元测试。

  2. 你说MyMethod很复杂,你想测试一下里面的代码流程。如果里面有多个路径,你还是要为每个路径写一个单元测试,那么为什么不能检查调用MyMethod的结果而不是检查它的内部呢?

    另一个想法是尝试将 MyMethod 重构为更容易测试的方法(如果您进行测试驱动开发,这几乎是自动的,如果您想做认真的单元测试,我推荐这种做法。“稍后测试”方法几乎总是会导致代码更难测试)。

  3. 如果您仍然想检查 MyMethod 的内部工作原理,也许您可​​以重构您需要将其检查到另一个类中的私有方法(在您的示例中说“计算”)。

    然后您可以使用模拟框架(例如RhinoMocks)来模拟该类。该框架允许您定义期望以什么顺序调用哪些函数以及它们应该返回什么。

    通常,您使用模拟来减少单元测试的环境要求,但您也可以以这种方式使用它们。