我试图验证我的日志警告消息是否是通过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方法而不是水平方法。
我错过了什么?
答案 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));
}