为什么没有Times.Always在Moq?

时间:2012-01-17 16:25:07

标签: c# unit-testing moq

使用Moq,可以使用Times.Never验证使用某些参数(即满足某些谓词的参数)调用方法从不

但是如何验证,无论一个方法被调用多少次,用某些参数调用总是

默认值为Times.AtLeastOnce

没有Times.Always。我错过了一些明显的东西吗谢谢!

编辑:上周我向Moq邮件列表发布了一条建议,但看起来它还没有被审核。我会在这里发布任何更新。

编辑:一个例子。假设我正在测试一个生成XML文档的类。我想确保只生成有效的文档。换句话说,测试编写器依赖项只能给出有效的文档,并使用有效的序列号来编写。

should_only_write_valid_xml_documents

Mock.Get(this.writer).Verify(
    w => w.Write(
        It.Is<XDocument>(doc => XsdValidator.IsValid(doc)),
        It.Is<int>(n => n < 3)),
    Times.Always);

4 个答案:

答案 0 :(得分:8)

多少次'总是?' Moq跟踪某些方法使用某些参数调用的所有时间,然后使用该数字与Times.Never,Times.AtLeastOnce等进行比较

所以,如果一个方法被执行了4次并且你将它设置为'Times.Always',这甚至意味着什么?

Times.Never会检查以确保该数字为零。

Times.AtLeastOnce将检查该数字是否大于或等于一。

Times.Always会检查号码是......?

您可以确定它应该以编程方式运行的次数,然后执行以下操作:

Times.Exactly(calculatedAmount)

但是,Moq无法知道“永远”意味着什么。

答案 1 :(得分:3)

听起来你想要“严格”的模拟行为。如果使用除预期参数之外的任何其他方法调用该方法,则测试将失败。

这在Moq中可用:

var mock = new Mock<IFoo>(MockBehavior.Strict);

(取自Moq QuickStart的例子。)

模拟上的每次调用现在必须具有相应的Setup

使用严格的模拟往往导致脆弱的测试。我会避免使用这种技术,或至少谨慎使用它。

答案 2 :(得分:2)

您可以应用逻辑反转来验证ALWAYS。

E.g:

假设您要进行以下验证:

mock.Verify(x => x.Method(It.Is<int>(i => i == 10)), Times.Always());

您只需将其替换为:

mock.Verify(x => x.Method(It.Is<int>(i => i != 10)), Times.Never());

答案 3 :(得分:0)

我的建议是使用It.IsAny条件为方法创建“后备”匹配。然后,您可以在该匹配上验证Times.Never,该匹配应始终被更具体的匹配所取代。