我有一个ILogger接口,其中包含LogTrace(string value, params object[] parameters)方法。现在我想要验证是否调用了LogTrace方法,并且要记录的字符串中包含某个id。问题是它可能被不同地调用。例如: 1)LogTrace("MyString "+ id) 2)LogTrace("MyString {0}", id) 等等。
是否有一种好的方法可以使用Moq来验证所有情况?我只能想到创建一个手工模拟对象,将格式化的字符串用于验证。
mock.Verify( m => m.LogTrace( It.IsAny<string>(), It.IsAny<object[]>() ) );
params object[]
对象以object[]
的形式传递给方法,因此您只需以某种方式匹配数组即可(例如上面所示,这将接受任何内容)。
如果您需要更多控制列表,请使用It.Is
匹配器,它允许您创建自己的谓词:
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
) ) );
这个示例展示了如何验证参数列表不为空,并且只包含一种类型为int
的参数5
。
mock.Verify(m => m.LogTrace(
It.Is<string>(s => !s.Contains(id)),
It.Is<object[]>(o => !o.Contains(id))), Times.Never());
var mock = new Mock<ILogger>();
string trace = null;
mock.Setup(l => l.LogTrace(It.IsAny<string>(), It.IsAny<object[]>()))
.Callback((s1, par) =>
{
trace = string.Format(s1, par);
});
//rest of the test
Assert.AreEqual(expected, trace);
ILogger
接口很小,您可以考虑手动实现存根(保留应记录的所有行),并在测试结束时进行验证。如果有多个行被记录,则这将是一个更易读的设置。