假设我有以下方法叫做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
}
答案 0 :(得分:1)
在这种情况下,您可以为函数提供数据,以便函数签名为public List<MyClass> DoSomething(List<MyClass data)
然后您的函数只有一个责任,那就是格式化数据。
如果您仍想使用您的函数进行数据获取,并且您将访问数据库或外部服务,我将使用依赖注入和模拟来测试该函数。
通常,如果可能,最好避免依赖。当然,这完全取决于你在课堂上不做任何其他数据提取的情况,这只是你要发送依赖的距离。
答案 1 :(得分:0)
伪方法究竟与覆盖方法有何不同?在这两种情况下,您最有可能最终必须创建从您要测试的类继承的新类。
无论如何,说实话,我没有看到太多差异,IMO你有两个选择:
两者都有效,没有一种比其他更好。 提取和覆盖的问题在于您需要额外的类型/文件。这当然意味着需要手工管理更多东西 - 如果可以避免,那应该是。就个人而言,当现有的模拟框架无法处理您的场景时,我会选择 。
模拟/注入技术的主要优点是它会迫使您做出更好的设计 - 考虑到SOLID原则并且编写更多可测试/可管理的代码。更不用说,有很多框架支持这种技术(Moq,RhinoMocks,FakeItEasy - 来命名最受欢迎的技术。)