C# 使用moq验证对带有param参数的函数的调用
我有一个带有LogTrace(字符串值,params object[]参数)的ILogger接口。现在,我想验证是否调用了LogTrace,并且要记录的字符串是否包含一些id。问题是,可以以不同的方式调用它。例如。 1) 日志跟踪(“MyString”+id) 2) 日志跟踪(“MyString{0}”,id) 等等C# 使用moq验证对带有param参数的函数的调用,c#,function,moq,C#,Function,Moq,我有一个带有LogTrace(字符串值,params object[]参数)的ILogger接口。现在,我想验证是否调用了LogTrace,并且要记录的字符串是否包含一些id。问题是,可以以不同的方式调用它。例如。 1) 日志跟踪(“MyString”+id) 2) 日志跟踪(“MyString{0}”,id) 等等 Moq是否有一个好方法来验证所有场景?我只能考虑创建一个手工制作的模拟,它将格式化可用于验证的字符串。您可以尝试使用回调,但它会变得相当复杂(未经测试): var mock=new
Moq是否有一个好方法来验证所有场景?我只能考虑创建一个手工制作的模拟,它将格式化可用于验证的字符串。您可以尝试使用
回调
,但它会变得相当复杂(未经测试):
var mock=new mock();
字符串跟踪=null;
mock.Setup(l=>l.LogTrace(It.IsAny(),It.IsAny())
.回调((s1,par)=>
{
trace=string.Format(s1,par);
});
//剩下的测试
Assert.AreEqual(预期,跟踪);
如果<代码> ILogger <代码>有一个小的接口,您可以考虑手动实现一个存根(它将保留所有应该记录的行),并在测试结束时验证它。如果您记录了多行,那么这将是一个更可读的设置
mock.Verify( m => m.LogTrace( It.IsAny<string>(), It.IsAny<object[]>() ) );
此示例显示如何验证参数列表是否为空,是否包含
5
作为类型int
的唯一参数。我认为这里没有一种简单的方法来完成您需要的操作。问题在于,您需要确保将某些值的组合传递给您的方法,这会导致许多不同的可验证场景:
- 字符串包含ID,参数包含ID-pass
- 字符串包含 ID和参数不包含ID-pass
- 字符串不包含 ID和参数包含ID=pass
- 字符串不包含ID和 参数不包含ID-失败
mock.Verify(m => m.LogTrace(
It.Is<string>(s => !s.Contains(id)),
It.Is<object[]>(o => !o.Contains(id))), Times.Never());
mock.Verify(m=>m.LogTrace(
它是(s=>!s.Contains(id)),
It.Is(o=>!o.Contains(id)),Times.Never();
我们在这里要做的是验证是否满足失败条件——也就是说,字符串不包含id,对象数组也不包含id。我们使用Times.Never()来确保这种情况永远不会发生
但是,请记住,代码乍一看可能并不明显;一旦你写了它,一定要正确地解释你的意图。它变得更加复杂,因为它并不总是一次调用,我也需要验证。我刚刚测试了我的参数是否等于id,但我正在考虑为此编写我自己的存根我知道它已经通过了,但这样我就不知道它是否包含了我想在那里看到的id。我现在就是这样做的,但是如果日志记录方法确实将id作为参数传递,这将不会有帮助,而是执行类似“id=”的操作 + 5. 我只是想让它少一点fragile@IlyaChernomordik例如我不明白。您是否可以编辑您的答案,并包含一个完整的示例,说明您希望接受什么和拒绝什么?这是一个有趣的建议,但很难验证日志记录是否被调用了2次。这只是包括另一个verify()以确保调用了该方法,在这个断言之前或之后。无论您调用LogTrace多少次,此测试都应确保记录的字符串始终包含id。您确实应该编写额外的断言,以确保至少调用一次该方法。
mock.Verify( m => m.LogTrace( It.IsAny<string>(),
It.Is<object[]>(ps =>
ps != null &&
ps.Length == 1 &&
ps[0] is int &&
(int)ps[0] == 5
) ) );
mock.Verify(m => m.LogTrace(
It.Is<string>(s => !s.Contains(id)),
It.Is<object[]>(o => !o.Contains(id))), Times.Never());