Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 何时使用模拟、伪造或覆盖?_C#_.net_Unit Testing_Mocking_Tdd - Fatal编程技术网

C# 何时使用模拟、伪造或覆盖?

C# 何时使用模拟、伪造或覆盖?,c#,.net,unit-testing,mocking,tdd,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

假设我有下面的方法叫做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
}
public List DoSomething()
{
List data=GetData();
如果(data.Count==0)
返回新列表();
数据=GetFormattedData(数据);
如果(data.Count==0)
返回新列表();
返回数据;
}
[测试]
公共无效DoSomething_NoData_ReturnsEmptyList()
{
//更改方法参数以传入公开GetData方法的IDataProvider
//创建实现IDataProvider的FakeProvider类
//确保FakeProvider.GetData不返回任何数据
//创建从DoSomething类继承类的FakeClass
//使FakeClass.GetData不返回任何数据
//当在测试中调用DoSomething时,它将调用父类
//创建DoSomething/GetData/GetFormattedData所在类的模拟
//告诉mock确保GetData返回空列表
//在测试中调用DoSomething
}
[测试]
public void DoSomething_NoFormattedData_ReturnsEmptyList()
{
//同样的可能性如上所述
}
伪方法和覆盖方法到底有什么不同?在这两种情况下,您很可能最终不得不创建一个新类来继承您想要测试的类

无论如何,老实说,我看不出有什么不同,在我看来,你有两个选择:

  • 模拟(需要位重新设计和依赖项注入)
  • 覆盖(称为提取和覆盖)
两者都是有效的,没有一个比另一个更好。提取和重写的问题是,您需要额外的类型/文件。这当然意味着更多的东西需要手工管理——如果可以避免的话,就应该避免。就我个人而言,只有当现有的模拟框架无法处理您的场景时,我才会选择这个


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

在这种情况下,您可以向函数提供数据,这样函数签名将是
公共列表DoSomething(ListWhat does
GetData()
do?另外,
DoSomething
是一个方法,而不是一个类。从来没有说过它是一个类。GetData转到数据库并返回列表GetData()时,您不应该也测试一下会发生什么吗返回null?同样的问题也适用于GetFormattedData。这不是使用数据库,这只是接收列表并对其执行一些逻辑。如何测试返回空列表的方法?如果该类的格式数据是私有的,那么您将永远无法进入该状态,因为您将检查是否从GetData获得结果函数。如果不返回。因此不应该是这种情况,您感兴趣的是函数的行为,结果是如果它没有获得任何数据,它将返回一个空列表。无论是FormatData还是DoSomething()测试时,只要相同输入的结果保持不变,就不希望在更改实现时测试中断。