模拟记录器给我ASP.NET Core的错误

时间:2017-01-04 20:13:11

标签: asp.net logging

我试图验证我的日志警告消息是否是通过NUnit模拟来写的。我收到此错误消息:

  

类型' System.NotSupportedException'的例外情况发生在Moq.dll中但未在用户代码中处理

其他信息:对非虚拟(VB中可覆盖)成员的验证无效:m => m.LogWarning(String.Format("comments not found for part number :{0}", (Object)0), new[] { "111" }

代码:

mockLogger.Verify(m => m.LogWarning($"comments not found for part number :{0}", "111"), Times.Exactly(1));

这种情况正在发生,因为NUnit模拟框架不支持扩展方法。堆栈溢出的一些人建议使用Log方法而不是水平方法。

我错过了什么?

1 个答案:

答案 0 :(得分:0)

首先,你不需要字符串开头的$。这是字符串插值。 LogWarning消息正在执行string.format,因此是{0}

模拟框架不能直接模拟静态方法。您的案例中的问题是 LogWarning 方法 - 这是静态(扩展)方法。

克服此问题的最简单方法是使用包装器类。在你的情况下,这就是我得到它的方式。

首先我创建了一个界面

public interface IMyLogWarning
{
    void LogWarning(string msg, params object[] args);
}

然后我创建了一个实现该接口的类

public class MyLogWarning<T> : IMyLogWarning where T : class
{
    private readonly ILogger _logger;

    public MyLogWarning(ILogger<T> logger)
    {
        // Using constructor for DI
        _logger = logger;
    }

    public void LogWarning(string msg, params object[] args)
    {
        _logger.LogWarning(msg, args);
    }
}

这两个原因是我将在我的代码和单元测试中使用这些。

该类中的构造函数已设置好,因此可以使用依赖注入来填充它,就像在ConfigureServices方法中一样。随意改变这一点;对我来说是一个快速刺痛。

services.AddTransient<IMyLogWarning, MyLogWarning<MyViewModel>>(); 

然后,您可以创建一个大致类似于

的单元测试
[Test]
public void LoggingTest_LogAMessage_ConfirmedLogWasRun()
{
    // TODO - add the rest of your test code

    // Arrange
    var warningMsg = "comments not found for part number :{0}";
    var partNumber = "111";
    var mockLogger = new Mock<IMyLogWarning>();

    // Act
    mockLogger.Object.LogWarning(warningMsg, partNumber);

    // Assert
    mockLogger.Verify(m => m.LogWarning(warningMsg, partNumber), Times.Exactly(1));
}