.net 测试日志的最佳方法?

.net 测试日志的最佳方法?,.net,logging,moq,xunit,.net,Logging,Moq,Xunit,我的代码使用ILogger记录,如下所示: public class Calculator { private readonly ILogger _logger; public Calculator(ILogger<Calculator> logger) { _logger = logger; } public int Sum(int x, int y) { int sum = x + y;

我的代码使用ILogger记录,如下所示:

public class Calculator
{
    private readonly ILogger _logger;

    public Calculator(ILogger<Calculator> logger)
    {
        _logger = logger;
    }

    public int Sum(int x, int y)
    {
        int sum = x + y;

        _logger.LogInformation("The sum of {x} and {y} is {sum}.", x, y, sum);

        return sum;
    }
}
公共类计算器
{
专用只读ILogger\u记录器;
公共计算器(ILogger记录器)
{
_记录器=记录器;
}
公共整数和(整数x,整数y)
{
整数和=x+y;
_logger.LogInformation({x}和{y}的和是{sum}。”,x,y,sum);
回报金额;
}
}
现在我想确定,当我调用Sum(2,3)时,LogInformation包含数字2、3和5。 如何在Xunit(Moq)中捕捉到这一点?

如果是我,我会使用(免责声明:我是作者)来构建表达式。它正是为了这个目的而设计的,并提供了一个简单易读的语句

loggerMock.Verify(Log.With.LogLevel(LogLevel.Information).And.LogMessage("The sum of {x} and {y} is {sum}.").And.LoggedValue("x", 2).And.LoggedValue("y", 3).And.LoggedValue("sum", 5), Times.Once);
如果您想自己滚动,则需要在
Log
方法上执行验证,并在日志级别和包含消息/记录值的只读列表上进行匹配

日志级别很简单。要匹配消息/记录的值,您需要在
TState
参数(第三个参数)上添加匹配器,如下所示:

var loggerMock = new Mock<ILogger<Calculator>>();
var logger = loggerMock.Object;
var calculator = new Calculator(logger);

calculator.Sum(2, 3);

loggerMock.Verify(l => l.Log(
    It.Is<LogLevel>(x => x.Equals(LogLevel.Information)),
    It.IsAny<EventId>(),
    It.Is<It.IsAnyType>((o, t) =>
        ((IReadOnlyList<KeyValuePair<string, object>>)o).Last().Value.ToString().Equals("The sum of {x} and {y} is {sum}.") &&
        ((IReadOnlyList<KeyValuePair<string, object>>)o).Any(y => y.Key.Equals("x") && y.Value.Equals(2)) &&
        ((IReadOnlyList<KeyValuePair<string, object>>)o).Any(y => y.Key.Equals("y") && y.Value.Equals(3)) &&
        ((IReadOnlyList<KeyValuePair<string, object>>)o).Any(y => y.Key.Equals("sum") && y.Value.Equals(5))
    ),
    It.IsAny<Exception>(),
    (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
Times.Once);
var loggerMock=new Mock();
var logger=loggerlock.Object;
var计算器=新计算器(记录器);
计算器。总和(2,3);
验证(l=>l.Log(
Is(x=>x.Equals(LogLevel.Information)),
It.IsAny(),
它是((o,t)=>
((IReadOnlyList)o.Last().Value.ToString().Equals({x}和{y}之和为{sum})。)&&
((IReadOnlyList)o).Any(y=>y.Key.Equals(“x”)和&y.Value.Equals(2))&&
((IReadOnlyList)o).Any(y=>y.Key.Equals(“y”)&&y.Value.Equals(3))&&
((IReadOnlyList)o).Any(y=>y.Key.Equals(“sum”)&&y.Value.Equals(5))
),
It.IsAny(),
(Func)It.IsAny()),
次,一次),;
在TState的封面下是一个
FormattedLogValues
对象,它实现了
IReadOnlyList
FormattedLogValues
在.NET Core 3.*中是内部的,因此您无法访问它。最后一项是
{OriginalFormat}
,它是提供给记录器的日志消息