C# 嵌套方法的单元测试
假设我有这样的服务:C# 嵌套方法的单元测试,c#,unit-testing,mocking,moq,C#,Unit Testing,Mocking,Moq,假设我有这样的服务: public class MyService : IMyService { public void DoStuff(IDependency dependency, string value) { dependency.SomeMethod(value, true); DoOtherStuff(dependency); } public void DoOtherStuff(IDependency depende
public class MyService : IMyService
{
public void DoStuff(IDependency dependency, string value)
{
dependency.SomeMethod(value, true);
DoOtherStuff(dependency);
}
public void DoOtherStuff(IDependency dependency)
{
// do some stuff
}
}
现在,当单元测试MyService
时,我可以很容易地模拟依赖关系,并测试依赖关系是否正确使用:
public void MyServiceTest()
{
// Arrange
var mockDependency = new Mock<IDependency>();
mockDependency.Setup(m => m.SomeMethod());
var service = new MyService();
// Act
service.DoStuff(mockDependency.Object, "value");
// Assert
mockDependency.Verify(v => v.SomeMethod(), Times.Once);
}
public void myservice测试()
{
//安排
var mockDependency=new Mock();
mockDependency.Setup(m=>m.SomeMethod());
var service=newmyservice();
//表演
service.DoStuff(mockDependency.Object,“value”);
//断言
验证(v=>v.SomeMethod(),Times.Once);
}
如何测试服务是否调用
DoOtherStuff
?或者这是一种糟糕的模式?正确的方法是什么?对于另一个类,您将使用moq,如前所述
但是,该类正在测试中,我认为您不应该在测试中分离这两个方法,原因类似于您不测试私有方法。归根结底,如果代码经过重构,在测试失败时不会调用第二个方法。不,公共API不受影响
最好像您现在所做的那样,对调用DoOtherStuff时的依赖性做出断言。对于另一个类,您将使用moq,如前所述 但是,该类正在测试中,我认为您不应该在测试中分离这两个方法,原因类似于您不测试私有方法。归根结底,如果代码经过重构,在测试失败时不会调用第二个方法。不,公共API不受影响
最好像您现在所做的那样,对DoOtherStuff所称的依赖性进行断言。您不应该关心单元测试,只要特定的公共功能满足契约,它是如何实现的 注意:上面的“public”一般用于“外部可用”,通常与C#
public
一致,但有时您希望/必须将其他方法标记为public,即使它实际上不是外部合同的一部分
如果您确实必须测试调用了
DoOtherStuff
,您可以将该方法设置为虚拟的并使用测试实现,该实现提供了自己的版本,以某种方式通知您调用(可能Moq也可以为您构建一个).您不应该关心单元测试,只要特定的公共功能满足其契约,它是如何实现的
注意:上面的“public”一般用于“外部可用”,通常与C#public
一致,但有时您希望/必须将其他方法标记为public,即使它实际上不是外部合同的一部分
如果您确实必须测试调用了DoOtherStuff
,您可以将该方法设置为虚拟的并使用测试实现,该测试实现提供了自己的版本,以某种方式通知您调用(可能Moq也可以为您构建一个)。作为注释(故意不在答案正文中加入),如果这些方法是虚拟的,您可以在测试中重写它们。然而,在大多数情况下,我并不认为这是一件非常有帮助的事情。我认为我们之所以关心某件事被称为“时代”的核心是因为它是类与类之间的互动。还有Delegate.CreateDelegate(元数据等)
。也有黑暗面的方式,但我并不十分熟悉。作为说明(故意不在答案正文中),如果方法是虚拟的,您可以在测试中重写它们。但是,我认为在大多数情况下,这不是一件非常有用的事情。我认为我们关心的核心是什么东西会被多次调用。一次是因为它是类之间的交互。还有Delegate.CreateDelegate(元数据等
。黑暗面也有出路,但我并不十分熟悉。