使用 NSubstitute 断言接收到的 ILogger 调用不匹配
Assert on received ILogger calls using NSubstitute doen't matches
我在执行 ILogger
调用匹配测试时遇到问题,当时测试的方法抛出异常,我真的不明白是什么原因。
这就是我的测试方法:
public async Task My_test_method()
{
//Arrange
var _logger = Substitute.For<ILogger<MyType>>();
var _mockedInnerService = Substitute.For<IMockedInnerService>();
var _testedService = new TestedService(_mockedInnerService, _logger);
var errorMessage = "Some problem";
_mockedInnerService
.When(async _self => await _self.SomeMethod(Arg.Any<string>(), Arg.Any<string>()))
.Do(_self => throw new Exception(errorMessage));
var expectedMessage = $"Error: {errorMessage}";
var methodParameters = new List<Guid>() { Guid.NewGuid() };
//Act
var results = await _testedService.TestedCall(methodParameters);
//Assert
await _mockedInnerService
.Received(1)
.SomeMethod(Arg.Any<string>(), Arg.Any<string>());
results
.Should()
.BeEmpty();
_logger
.Received(1)
.LogError(Arg.Is<string>(message => message == expectedMessage));
}
这就是我测试过的方法:
public async Task<IList<SomeObject>> TestedCall(IList<Guid> ids)
{
IList<object> results = null;
try
{
units = await _innerService.SomeMethod("arg", "arg");
}
catch (Exception e)
{
var msg = "Some problem";
_logger.LogError(msg);
}
return results == null
? new List<object>()
: results.Select(s => new SomeObject(s.Id, s.Code)).ToList();
}
测试失败,结果如下:
Message:
NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching:
Log<Object>(Error, 0, [null], <null>, Func<Object, Exception, String>)
Actually received no matching calls.
Received 1 non-matching call (non-matching arguments indicated with '*' characters):
Log<Object>(Error, 0, *Some problem*, <null>, Func<Object, Exception, String>)
你们能帮我理解我做错了什么吗?
谢谢
看起来ILogger<T>.LogError(string)
方法实际上是一个扩展方法。这意味着它将转换为引擎盖下的不同调用,即您在输出中看到的 Log<Object>(Error, 0, [null], <null>, Func<Object, Exception, String>)
。此方法调用可以有额外的参数,这些参数对于扩展方法的每次调用可能都不相同,因此您的实际调用和断言调用之间可能会有所不同。
要修复它,您可能必须断言底层方法,并使用 Arg.Any<T>()
使其忽略有问题的参数,这可能是最后的 Func<Object, Exception, String>
参数。
我在执行 ILogger
调用匹配测试时遇到问题,当时测试的方法抛出异常,我真的不明白是什么原因。
这就是我的测试方法:
public async Task My_test_method()
{
//Arrange
var _logger = Substitute.For<ILogger<MyType>>();
var _mockedInnerService = Substitute.For<IMockedInnerService>();
var _testedService = new TestedService(_mockedInnerService, _logger);
var errorMessage = "Some problem";
_mockedInnerService
.When(async _self => await _self.SomeMethod(Arg.Any<string>(), Arg.Any<string>()))
.Do(_self => throw new Exception(errorMessage));
var expectedMessage = $"Error: {errorMessage}";
var methodParameters = new List<Guid>() { Guid.NewGuid() };
//Act
var results = await _testedService.TestedCall(methodParameters);
//Assert
await _mockedInnerService
.Received(1)
.SomeMethod(Arg.Any<string>(), Arg.Any<string>());
results
.Should()
.BeEmpty();
_logger
.Received(1)
.LogError(Arg.Is<string>(message => message == expectedMessage));
}
这就是我测试过的方法:
public async Task<IList<SomeObject>> TestedCall(IList<Guid> ids)
{
IList<object> results = null;
try
{
units = await _innerService.SomeMethod("arg", "arg");
}
catch (Exception e)
{
var msg = "Some problem";
_logger.LogError(msg);
}
return results == null
? new List<object>()
: results.Select(s => new SomeObject(s.Id, s.Code)).ToList();
}
测试失败,结果如下:
Message:
NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching:
Log<Object>(Error, 0, [null], <null>, Func<Object, Exception, String>)
Actually received no matching calls.
Received 1 non-matching call (non-matching arguments indicated with '*' characters):
Log<Object>(Error, 0, *Some problem*, <null>, Func<Object, Exception, String>)
你们能帮我理解我做错了什么吗?
谢谢
看起来ILogger<T>.LogError(string)
方法实际上是一个扩展方法。这意味着它将转换为引擎盖下的不同调用,即您在输出中看到的 Log<Object>(Error, 0, [null], <null>, Func<Object, Exception, String>)
。此方法调用可以有额外的参数,这些参数对于扩展方法的每次调用可能都不相同,因此您的实际调用和断言调用之间可能会有所不同。
要修复它,您可能必须断言底层方法,并使用 Arg.Any<T>()
使其忽略有问题的参数,这可能是最后的 Func<Object, Exception, String>
参数。