使用 Moq 中的任何结构参数验证方法调用

Nic*_*ler 7 c# moq asp.net-core

将我的应用程序从 ASP.NET Core 2.2 迁移到 ASP.NET Core 3.0 时,我遇到了以下问题:

我有一个在某些情况下应该记录错误消息的类。这是通过调用LogErrorILogger<MyClass>

我曾经用我的单元测试中的以下片段来验证这一点:

Mock<ILogger<MyClass>> loggerMock = ...;
MyClass myClass = ...;

myClass.MethodThatLogsTestException();

loggerMock.Verify(l => l.Log(
    It.IsAny<LogLevel>(),
    It.IsAny<EventId>(),
    It.IsAny<object>(),
    It.IsAny<TestException>(),
    It.IsAny<Func<object, Exception, string>>())
);
Run Code Online (Sandbox Code Playgroud)

现在问题来了:

在 ASP.NET Core 2.2 中,第三个参数(Mocked via It.IsAny<object>())是内部类型FormattedLogValues。这是一堂课,所以It.IsAny<object>()奏效了。在 ASP.NET Core 3.0 中,它已更改为结构体,因此It.IsAny<object>()不再匹配它。

如何让我的Verify()电话在 ASP.NET Core 3.0 中工作?是否有It.IsAny()匹配任何结构类型的版本?

编辑:这是一个完全可运行的代码段,它在 ASP.NET Core 3.0 上失败并在 ASP.NET Core 2.2 上成功。

public class Test
{
    public class Impl
    {
        private readonly ILogger<Impl> logger;

        public Impl(ILogger<Impl> logger)
        {
            this.logger = logger;
        }

        public void Method()
        {
            logger.LogError(new Exception(), "An error occurred.");
        }
    }

    [Fact]
    public void LogsErrorOnException()
    {
        var loggerMock = new Mock<ILogger<Impl>>();
        var sut = new Impl(loggerMock.Object);

        sut.Method();

        loggerMock.Verify(l => l.Log(
            It.IsAny<LogLevel>(),
            It.IsAny<EventId>(),
            It.IsAny<object>(),
            It.IsAny<Exception>(),
            It.IsAny<Func<object, Exception, string>>())
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*ler 5

更改It.IsAny<Func<object, Exception, string>>())(Func<object, Exception, string>) It.IsAny<object>()似乎可以解决问题。如果您使用的是 Moq 4.13+,object 也可以替换为。IsAnyType

在内部,Logger 类用作FormattedLogValues状态参数(object在我的示例中)。结构的改变似乎与此有关。具体原因是什么我也不清楚。但 Moq GitHub 存储库上似乎有一个问题描述了更多细节。目前似乎还没有具体的解释为什么它曾经有效,但更多信息可能很快就会发布在那里。

https://github.com/moq/moq4/issues/918