fos*_*ndy 58 c# unit-testing moq
设置如下:
public interface IFoo
{
void Fizz();
}
[Test]
public void A()
{
var foo = new Mock<IFoo>(MockBehavior.Loose);
foo.Object.Fizz();
foo.Verify(x => x.Fizz());
// stuff here
foo.Verify(x => x.Fizz(), Times.Never()); // currently this fails
}
Run Code Online (Sandbox Code Playgroud)
基本上我想// stuff here在foo.Verify(x => x.Fizz(), Times.Never())传递中输入一些代码.
因为这可能构成moq/unit测试滥用,我的理由是我可以这样做:
[Test]
public void Justification()
{
var foo = new Mock<IFoo>(MockBehavior.Loose);
foo.Setup(x => x.Fizz());
var objectUnderTest = new ObjectUnderTest(foo.Object);
objectUnderTest.DoStuffToPushIntoState1(); // this is various lines of code and setup
foo.Verify(x => x.Fizz());
// reset the verification here
objectUnderTest.DoStuffToPushIntoState2(); // more lines of code
foo.Verify(x => x.Fizz(), Times.Never());
}
Run Code Online (Sandbox Code Playgroud)
基本上,我有一个状态对象,其中需要进行相当多的工作(在制作各种模拟对象和其他模拟对象方面)将其推入State1.然后我想测试从State1到State2的转换.我没有重复或抽象代码,而是只重新使用State1测试,将其推入State2并执行我的断言 - 除了验证调用之外,我可以做所有这些操作.
sta*_*low 114
我想在创建这篇文章很久之后,他们添加了OP要求的功能,有一个名为Moq.MockExtensions.ResetCalls()的Moq扩展方法.
使用此方法,您可以完全按照您的意愿执行,如下所示:
[Test]
public void Justification()
{
var foo = new Mock<IFoo>(MockBehavior.Loose);
foo.Setup(x => x.Fizz());
var objectUnderTest = new ObjectUnderTest(foo.Object);
objectUnderTest.DoStuffToPushIntoState1(); // this is various lines of code and setup
foo.Verify(x => x.Fizz());
foo.ResetCalls(); // *** Reset the verification here with this glorious method ***
objectUnderTest.DoStuffToPushIntoState2(); // more lines of code
foo.Verify(x => x.Fizz(), Times.Never());
}
Run Code Online (Sandbox Code Playgroud)
更新
现在我们应该在库的最新版本上使用.Invocations.Clear()代替.ResetCalls():
foo.Invocations.Clear()
Run Code Online (Sandbox Code Playgroud)
Cod*_*ler 10
添加@stackunderflow 的回答(哈哈,不错的昵称:))
在 Moq 的后续版本中,Moq.MockExtensions.ResetCalls()被标记为已过时。mock.Invocations.Clear()应该使用:
foo.Invocations.Clear();
Run Code Online (Sandbox Code Playgroud)
我不认为你可以重置像这样的模拟.相反,如果你知道Fizz在转换到状态1时应该调用一次,你可以像这样进行验证:
objectUnderTest.DoStuffToPushIntoState1();
foo.Verify(x => x.Fizz(), Times.Once()); // or however many times you expect it to be called
objectUnderTest.DoStuffToPushIntoState2();
foo.Verify(x => x.Fizz(), Times.Once());
Run Code Online (Sandbox Code Playgroud)
话虽如此,我仍然会为此创建两个单独的测试.作为两个测试,更容易看出转换到状态1是否失败,或者转换到状态2是否失败.此外,当像这样一起测试时,如果您转换到状态1失败,则测试方法退出,并且您转换到状态2不会被测试.
编辑
作为一个例子,我用xUnit测试了以下代码:
[Fact]
public void Test()
{
var foo = new Mock<IFoo>(MockBehavior.Loose);
foo.Object.Fizz();
foo.Verify(x => x.Fizz(), Times.Once(), "Failed After State 1");
// stuff here
foo.Object.Fizz();
foo.Verify(x => x.Fizz(), Times.Once(), "Failed after State 2");
}
Run Code Online (Sandbox Code Playgroud)
此测试失败,并显示消息"状态2后失败".这模拟了如果你的方法将foo推入状态2调用会发生什么Fizz.如果是,第二个Verify将失败.
再次,在你的代码看,因为你调用一个方法来验证它/不会调用其他方法的模拟,我想你需要设置CallBase,以true使基地DoStuffToPushIntoState2被称为而非模拟的覆盖.
| 归档时间: |
|
| 查看次数: |
25782 次 |
| 最近记录: |