【问题标题】:When to use Mock or Fake or Overrides?何时使用 Mock、Fake 或 Overrides?
【发布时间】:2012-01-27 09:35:18
【问题描述】:

假设我有以下称为 DoSomething 的方法。

在编写单元测试时,我如何知道是使用 Fake、Mock 还是 Override 方法,以及为什么其中一种方法比另一种更好?

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
}

【问题讨论】:

  • GetData() 是做什么的?另外,DoSomething 是一个方法,而不是一个类。
  • 从来没有说过这是一门课。 GetData 转到数据库并返回 List
  • 你不应该也测试一下当 GetData() 返回 null 时会发生什么?

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


【解决方案1】:

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

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

如果可能的话,通常最好避免依赖。当然,这一切都取决于,如果您不在课堂上进行任何其他数据获取,那么这只是您将依赖项发送到多远的问题。

【讨论】:

  • 同样的问题也适用于 GetFormattedData。这不使用数据库,这只是在 List 上做一些逻辑。如何测试该方法是否返回一个空列表?
  • 如果格式数据是该类的私有数据,那么您将永远不会进入该状态,因为您检查是否从 GetData 函数获得结果。如果你不回来。所以这不应该是一个案例,你感兴趣的是函数的行为方式,结果是如果它没有得到任何数据,它会返回一个空列表。是 FormatData 还是 DoSomething() 返回都没有关系。在测试时,如果您更改实现,只要相同输入的结果保持不变,您不希望测试中断。
【解决方案2】:

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

不管怎样,老实说,我看不出有什么不同,IMO 你有两个选择:

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

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

模拟/注入技术的主要优点是它迫使您进行更好的设计 - 牢记SOLID 原则并总体编写更多可测试/可管理的代码。更不用说,有许多框架支持这种技术(MoqRhinoMocksFakeItEasy - 列出最流行的那些)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-21
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 2015-04-04
    相关资源
    最近更新 更多