使用Moq中的任何struct参数验证方法调用 [英] Verifying method call with any struct parameter in Moq

查看:111
本文介绍了使用Moq中的任何struct参数验证方法调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm running into the following problem when migrating my app from ASP.NET Core 2.2 to ASP.NET Core 3.0:

我有一个在某些情况下应该记录错误消息的类.这是通过在ILogger<MyClass>上调用LogError来完成的.

I have a class which should log an error message under certain circumstances. This is done by calling LogError on ILogger<MyClass>.

我以前使用单元测试中的以下代码片段对此进行了验证:

I used to verifiy this with the following snippet from my unit test:

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>>())
);

现在问题出在这里:

在ASP.NET Core 2.2中,第三个参数(通过It.IsAny<object>()模拟)是内部类型FormattedLogValues.这是一堂课,所以It.IsAny<object>()起作用了.在ASP.NET Core 3.0中,它已更改为结构,因此It.IsAny<object>()不再与之匹配.

In ASP.NET Core 2.2, the 3rd parameter (Mocked via It.IsAny<object>()) was of an internal type FormattedLogValues. This was a class, so It.IsAny<object>() worked. In ASP.NET Core 3.0 it was changed to a struct, so It.IsAny<object>() no longer matches it.

如何获得我的Verify()调用以在ASP.NET Core 3.0中工作?是否有与任何结构类型匹配的It.IsAny()版本?

How can I get my Verify() call to work in ASP.NET Core 3.0? Is there an It.IsAny() version that matches any struct type?

这是一个完全可运行的代码段,该代码段在ASP.NET Core 3.0上失败,而在ASP.NET Core 2.2上成功.

Here is a fully runnable snippet that fails on ASP.NET Core 3.0 and succeeds on 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>>())
        );
    }
}

推荐答案

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

Changing It.IsAny<Func<object, Exception, string>>()) to (Func<object, Exception, string>) It.IsAny<object>() seems to solve the problem. object can also be replace by IsAnyType if you're on Moq 4.13+.

内部,Logger类使用FormattedLogValues作为状态参数(在我的示例中为object).对结构的更改似乎与此有关.确切的原因是我不确定.但是Moq GitHub回购上似乎有一个问题描述了更多细节.似乎还没有一个具体的解释,为什么它曾经起作用,但是更多的信息可能很快就会发布在那里.

Internally the Logger class uses FormattedLogValues as the state parameter (the object in my example). The change to struct seems to have something to do with it. What exactly the cause is I'm not sure. But there seems to be an issue on the Moq GitHub repo describing a few more details. There doesn't seem to be a concrete explanation yet why it used to work, but more info will probably be posted there soon.

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

这篇关于使用Moq中的任何struct参数验证方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆