使用 Moq Verify 防止长 Visual Studio 测试跟踪输出

Prevent long Visual Studio test trace output with Moq Verify

我想使用 Moq 的 Verify 方法验证是否调用了一个方法。我的部分测试涉及大量循环,在此期间,除了我要验证的方法之外,我的模拟对象上的许多其他方法也被调用。

如果验证断言失败,在相关测试的 Visual Studio 测试资源管理器输出窗格中,除了有关验证失败原因的错误消息外,还列出了所有其他调用在模拟对象上制作,延伸到 1000 行。这使得测试资源管理器 window 在加载完整的异常详细信息之前变得无法使用,这有时可能需要几分钟。

有什么方法可以防止 Moq 列出所有其他已执行的调用?我只关心验证是否失败

复制问题的人为代码:

public interface IMyInterface
{
    void Foo();
    void Bar();
    void FooBar();
}

[TestClass]
public class TestClass1
{
    [TestMethod]
    public void TestMethod1()
    {
        using (var mock = AutoMock.GetLoose())
        {
            var myInterfaceMock = mock.Mock<IMyInterface>();
            var myInterfaceObj = myInterfaceMock.Object;

            for (var i = 0; i < 1000; i++)
            {
                myInterfaceObj.Foo();
                myInterfaceObj.Bar();
            }

            myInterfaceMock.Verify(x => x.FooBar(), Times.Once());
        }
    }
}

测试资源管理器输出,持续 1000 行(对于大尺寸、高 DPI 屏幕感到抱歉):

非常感谢

这不是使用 Verify() 的直接答案,否则会阻止 Moq 列出所有其他已执行的调用。

它使用 Callback 来计算方法 FooBar 被调用的次数。不知道你会不会喜欢这样的方式?


[TestMethod]
public void TestMethod1()
{
    int expectedCount = 1;
    int actualCount = 0;
    
    using (var mock = AutoMock.GetLoose())
    {
        var myInterfaceMock = mock.Mock<IMyInterface>();
        var myInterfaceObj = myInterfaceMock.Object;
        myInterfaceMock.Setup(mi => mi.FooBar()).Callback(() => actualCount++);

        for (var i = 0; i < 1000; i++)
        {
            myInterfaceObj.Foo();
            myInterfaceObj.Bar();
        }

        Assert.AreEqual( expectedCount, actualCount, $"Expected invocation on the mock was '{expectedCount}' times, but was called '{actualCount}' times");
    }
}

Output:

Assert.AreEqual failed. Expected:<1>. Actual:<0>. Expected invocation on the mock was '1' times, but was called '0' times

Verify 在条件失败时抛出异常,所以这看起来像是简单地捕获异常、解析消息然后用你想要的消息部分使测试失败的情况。考虑到消息的当前格式,这是微不足道的:

var myInterfaceMock = new Mock<IMyInterface>();
var myInterfaceObj = myInterfaceMock.Object;

for (var i = 0; i < 1000; i++)
{
    myInterfaceObj.Foo();
    myInterfaceObj.Bar();
}

try
{
    myInterfaceMock.Verify(x => x.FooBar(), Times.Once());
}
catch (MockException me) 
{       
    throw new Exception(me.Message.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)[0]);       
}

结果:

你如何通过测试取决于你,我刚刚作为 MVP 抛出了一个新的异常。 如果是我,我会把它放到扩展方法中以保持测试干净。您可能必须执行其中几个操作才能处理 Verify 重载。