gpt4 book ai didi

c# - 使用 Moq 和 xUnit 模拟和测试 LogError 消息

转载 作者:行者123 更新时间:2023-12-04 17:32:12 26 4
gpt4 key购买 nike

我有一个类级别的 ILogger,它是在构造函数中使用 ILoggerFactory 设置的。然后在该类中的方法中使用记录器,这完美地工作。

我正在努力研究如何模拟 ILogger 和 ILoggerFactory 以便我可以对 LogError 消息进行单元测试。谁能给我举个例子?

我使用 xUnit 和 Microsoft.Extentions.Logging 登录

//This is my unit test project
[Fact]
public void TestLogErrorMessage()
{
MyClass myClass = new MyClass (MockLoggerFactory().Object);

var result = myClass.Mymethod("a")

//How do I test the LogError message???
}


//Not sure if this is correct
private Mock<ILoggerFactory> MockLoggerFactory()
{
Mock<ILoggerFactory> mockLoggerFactory = new
Mock<ILoggerFactory>(MockBehavior.Default);
mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
.Returns(MockLogger().Object);

return mockLoggerFactory;
}

private Mock<ILogger> MockLogger()
{
var logger = new Mock<ILogger>();
return logger;
}
//This is the class/method i need to test
private readonly ILogger logger;

public MyClass(ILoggerFactory loggerFactory)
{
if (loggerFactory != null)
{
this.logger = loggerFactory.CreateLogger<MyClass>();
}
}


public string Mymethod(string msg)
{
if(msg = "a")
{
this.logger.LogError($"error");
}

return "a string";
}

最佳答案

你可以做这样的事情

(注意:这在这种特定情况下不起作用,因为 LogError 是一种扩展方法,请参阅下面的更新):

Mock<ILogger> _logger; // declare it somewhere where your test can access it

[Fact]
public void TestLogErrorMessage()
{
MyClass myClass = new MyClass(MockLoggerFactory().Object);

var result = myClass.Mymethod("a")

_logger.Verify();
}


private Mock<ILoggerFactory> MockLoggerFactory()
{
_logger = new Mock<ILogger>();
_logger.Setup(log => log.LogError(It.IsAny<string>())).Verifiable();
Mock<ILoggerFactory> mockLoggerFactory = new Mock<ILoggerFactory>(MockBehavior.Default);
mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
.Returns(_logger.Object);

return mockLoggerFactory;
}

需要注意的关键是调用 Verifiable()设置好后 ILogger mock 。您可以阅读更多关于 Verifiable() 的信息在 this SO question .测试运行后,您可以通过调用 .Verify() 来检查该方法是否被调用。在模拟上。

根据您的需要,您可以在测试类的构造函数中进行设置(如果所有/大多数测试都需要它)或直接在测试方法中进行设置。您也可以将它与 ILoggerFactory 一起返回。 .关键是要保留记录器,以便您可以验证该方法是否被调用。

对于您的特定情况(尝试验证对 ILogger.LogError 的调用),您不能模拟 LogError ,但底层方法 ILogger.Log .看起来像这样:
var formatter = new Func<It.IsAnyType, Exception, string>((a, b) => "");
m.Setup(x => x.Log<It.IsAnyType>(LogLevel.Error,
It.IsAny<EventId>(),
It.IsAny<It.IsAnyType>(),
It.IsAny<Exception>(),
formatter))
.Verifiable();

另一种选择是伪造 ILogger 的实现。并从 Mock<ILoggerFactory> 返回它:
mockLoggerFactory.Setup(_ => _.CreateLogger(It.IsAny<string>())
.Returns(new FakeLogger());

public class FakeLogger : ILogger
{
public static bool LogErrorCalled { get; set; }

public IDisposable BeginScope<TState>(TState state)
{
throw new NotImplementedException();
}

public bool IsEnabled(LogLevel logLevel) => true;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if(logLevel == LogLevel.Error)
{
LogErrorCalled = true;
}
}
}

然后在你的测试之后你可以检查是否 FakeLogger.LogErrorCalledtrue .这针对您的特定测试进行了简化 - 当然,您可以获得比这更详细的信息。

关于c# - 使用 Moq 和 xUnit 模拟和测试 LogError 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58630307/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com