何时使用Mock或Fake或Overrides?

时间:2012-01-27 09:35:19

标签: c# .net unit-testing mocking tdd

假设我有以下方法叫做DoSomething。

在编写单元测试时,我如何知道是使用假,模拟还是覆盖方法,为什么一个比另一个好?

public List<MyClass> DoSomething()
{
  List<MyClass> data = GetData();

  if (data.Count == 0)
    return new List<MyClass>();

  data = GetFormattedData(data);

  if (data.Count == 0)
    return new List<MyClass>();

  return data;
}

[Test]
public void DoSomething_NoData_ReturnsEmptyList()
{
  //Change method parameters to pass in IDataProvider that exposes GetData method
  //Create FakeProvider class implementing IDataProvider
  //Ensure FakeProvider.GetData returns no data

  //Create FakeClass that inherits class from DoSomething class
  //Make FakeClass.GetData return no data
  //When DoSomething is called in the test it will call the parent class

  //Create Mock of class that DoSomething/GetData/GetFormattedData is in
  //Tell mock to make sure GetData returns empty list
  //Call DoSomething in test
}

[Test]
public void DoSomething_NoFormattedData_ReturnsEmptyList()
{
   //Same possibilities exist as above
}

2 个答案:

答案 0 :(得分:1)

在这种情况下,您可以为函数提供数据,以便函数签名为public List<MyClass> DoSomething(List<MyClass data)然后您的函数只有一个责任,那就是格式化数据。

如果您仍想使用您的函数进行数据获取,并且您将访问数据库或外部服务,我将使用依赖注入和模拟来测试该函数。

通常,如果可能,最好避免依赖。当然,这完全取决于你在课堂上不做任何其他数据提取的情况,这只是你要发送依赖的距离。

答案 1 :(得分:0)

方法究竟与覆盖方法有何不同?在这两种情况下,您最有可能最终必须创建从您要测试的类继承的新类。

无论如何,说实话,我没有看到太多差异,IMO你有两个选择:

  • 模拟(需要进行位重新设计和依赖注入)
  • 覆盖(称为提取和覆盖

两者都有效,没有一种比其他更好。 提取和覆盖的问题在于您需要额外的类型/文件。这当然意味着需要手工管理更多东西 - 如果可以避免,那应该是。就个人而言,当现有的模拟框架无法处理您的场景时,我会选择

模拟/注入技术的主要优点是它会迫使您做出更好的设计 - 考虑到SOLID原则并且编写更多可测试/可管理的代码。更不用说,有很多框架支持这种技术(MoqRhinoMocksFakeItEasy - 来命名最受欢迎的技术。)