我刚刚开始阅读使用 C# 进行专业测试驱动开发:使用 TDD 开发真实世界应用程序
我很难理解存根、假货和模拟。据我目前了解,它们是用于对项目进行单元测试的假对象,并且模拟是一个带有条件逻辑的存根。
我想我已经了解到的另一件事是,模拟与依赖注入有某种关系,这是我昨天才设法理解的概念。
我不明白为什么我会实际使用它们。我似乎无法在网上找到任何能正确解释它们的具体例子。
谁能给我解释一下这个概念?
我刚刚开始阅读使用 C# 进行专业测试驱动开发:使用 TDD 开发真实世界应用程序
我很难理解存根、假货和模拟。据我目前了解,它们是用于对项目进行单元测试的假对象,并且模拟是一个带有条件逻辑的存根。
我想我已经了解到的另一件事是,模拟与依赖注入有某种关系,这是我昨天才设法理解的概念。
我不明白为什么我会实际使用它们。我似乎无法在网上找到任何能正确解释它们的具体例子。
谁能给我解释一下这个概念?
正如我过去所读到的,这就是我认为每个术语所代表的含义
存根
在这里,您将方法的结果存根到已知值,只是为了让代码运行没有问题。例如,假设您有以下内容:
public int CalculateDiskSize(string networkShareName)
{
// This method does things on a network drive.
}
你不关心这个方法的返回值是什么,它不相关。另外,如果网络驱动器不可用,则执行时可能会导致异常。因此,您将结果存根以避免该方法的潜在执行问题。
所以你最终会做类似的事情:
sut.WhenCalled(() => sut.CalculateDiskSize()).Returns(10);
伪造的
使用假货,您将返回假数据,或创建对象的假实例。一个经典的例子是存储库类。采取这种方法:
public int CalculateTotalSalary(IList<Employee> employees) { }
通常,上述方法将传递从数据库中读取的员工集合。但是,在您的单元测试中,您不想访问数据库。因此,您创建了一个虚假的员工列表:
IList<Employee> fakeEmployees = new List<Employee>();
然后,您可以将项目添加到 fakeEmployees 并断言预期结果,在本例中为总工资。
模拟
使用模拟对象时,您打算在这些模拟对象上验证某些行为或数据。例子:
您想验证在测试运行期间是否执行了特定方法,这是使用 Moq 模拟框架的通用示例:
public void Test()
{
// Arrange.
var mock = new Mock<ISomething>();
mock.Expect(m => m.MethodToCheckIfCalled()).Verifiable();
var sut = new ThingToTest();
// Act.
sut.DoSomething(mock.Object);
// Assert
mock.Verify(m => m.MethodToCheckIfCalled());
}
希望以上内容有助于澄清一些事情。
编辑:Roy Osherove 是测试驱动开发的知名倡导者,他有一些关于该主题的非常好的信息。您可能会发现它非常有用:
它们都是测试替身的变体。这是一个很好的参考,解释了它们之间的区别:http: //xunitpatterns.com/Test%20Double.html
此外,来自 Martin Fowler 的帖子:http ://martinfowler.com/articles/mocksArentStubs.html
Meszaros 使用术语 Test Double 作为通用术语,用于代替真实对象用于测试目的的任何类型的假装对象。这个名字来源于电影中特技替身的概念。(他的目标之一是避免使用任何已经被广泛使用的名称。)Meszaros 然后定义了四种特殊类型的双精度:
- 虚拟对象:被传递但从未实际使用过。通常它们仅用于填充参数列表。
- 假对象实际上有工作实现,但通常采取一些捷径,这使得它们不适合生产(内存数据库就是一个很好的例子)。
- 存根为测试期间拨打的电话提供预设答案,通常根本不响应任何超出测试程序的内容。存根还可以记录有关呼叫的信息,例如记住它“发送”的消息的电子邮件网关存根,或者可能只记录它“发送”的消息的数量。
- 模拟就是我们在这里讨论的内容:预先编程的对象具有期望,这些期望形成了它们期望接收的调用的规范。
在这些类型的替身中,只有模拟坚持行为验证。其他双打可以并且通常会使用状态验证。在练习阶段,Mocks 实际上确实表现得像其他替身,因为他们需要让 SUT 相信它正在与其真正的合作者交谈。
这个 PHP 单元的手册作为介绍帮助了我很多:
“有时很难测试被测系统 (SUT),因为它依赖于无法在测试环境中使用的其他组件。这可能是因为它们不可用,它们不会返回所需的结果“测试或因为执行它们会产生不良的副作用。在其他情况下,我们的测试策略要求我们对 SUT 的内部行为有更多的控制或可见性。” 更多:https ://phpunit.de/manual/current/en/test-doubles.html
在寻找“测试替身”时,我发现更好的“介绍”,因为模拟、假货、存根和其他都是众所周知的。