我目前正在尝试使以下代码在运行时成功:
public delegate void LogDelegate(LogLevel logLevel, EventId eventId, object state, Exception exception, Func<object, Exception, string> formatter);
public abstract class LoggingTestBase
{
private Mock<ILogger> _mockLogger;
public ILogger Setup(LogDelegate logCallback)
{
_mockLogger = new Mock<ILogger>(MockBehavior.Strict);
_mockLogger.Setup(logger => logger.Log(
It.IsAny<LogLevel>(),
It.IsAny<EventId>(),
It.IsAny<object>(),
It.IsAny<Exception>(),
It.IsAny<Func<object, Exception, string>>()))
.Callback(logCallback);
return _mockLogger.Object;
}
}
问题是,运行测试后我得到了MockException
,因为调用的方法是我显然没有设置的通用ILogger.Log<FormattedLogValues>(...)
。
阅读existing answer to this和Moq文档后得出的结论是,我可能应该只使用上面显示的正确类型参数来模拟通用方法。
在这里,我偶然遇到了下一个问题,这使我陷入了想法的末端:
在Microsoft.Extensions.Logging
的当前版本中,FormattedLogValues
不再是公共的,而是内部的(在this PR之后),这使得无法模拟最终调用的通用方法。
有人成功解决了这个问题吗? 怎么样?
答案 0 :(得分:1)
我有一个类似的问题。我只想验证是否已调用LogInformation。据此-> https://github.com/aspnet/Extensions/issues/1319可能应该由Moq解决。
但是,最后建议您可以使用It.IsAnyType而不是object。对于您来说,这就像:
_mockLogger.Setup(logger => logger.Log(
It.IsAny<LogLevel>(),
It.IsAny<EventId>(),
It.IsAny<It.IsAnyType>(),
It.IsAny<Exception>(),
(Func<It.IsAnyType, Exception, string>) It.IsAny<object>()))
.Callback(logCallback);
我无法使其正常运行,但是也许这可以将您推向正确的方向?
答案 1 :(得分:0)
此处解释并解决了验证解决方案:
https://adamstorr.azurewebsites.net/blog/mocking-ilogger-with-moq , the Github source is here。
我的个人情况不需要验证,只是围绕日志调用的最小起订量。所以我将代码修改为:
namespace my.xTests
{
public static class VerifyLoggingUtil
{
public static Mock<ILogger<T>> SetupLogging<T>(
this Mock<ILogger<T>> logger
)
{
Func<object, Type, bool> state = (v, t) => true;
logger.Setup(
x => x.Log(
It.Is<LogLevel>(l => true),
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((v, t) => state(v, t)),
It.IsAny<Exception>(),
It.Is<Func<It.IsAnyType, Exception, string>>((v, t) => true)));
return logger;
}
}
}
在我的 xUnit 测试设置中:
namespace my.xTests
{
public class myTests{
private Mock<Microsoft.Extensions.Logging.ILogger<sFTPAzFn.Logging>> moqlog;
private MockRepository mockRepository;
public myTests(){
this.mockRepository = new MockRepository(MockBehavior.Strict);
moqlog = this.mockRepository.Create<Microsoft.Extensions.Logging.ILogger<MyLoggingClass>>();
}
private IInterfaceUnderTest CreateService(){
var moqlogobject = moqlog.SetupLogging<MyLoggingClass>().Object;
return new ClassUnderTest(moqlogobject);
}
}
}