请问NSubstitute现在是否有类似Moq中It.IsAnyType的对应功能?
使用NSubstitute测试ILogger的解决方案
核心问题答复
NSubstitute 4.0及以上版本已经支持与Moq It.IsAnyType对等的泛型参数匹配能力,直接用Arg.Is<object>即可匹配任意类型的入参。如果你当前使用的是NSubstitute 3.x及以下版本,升级到4.0以上的最新稳定版即可支持该匹配能力。你之前的实现失败并非是NSubstitute缺少对应功能,而是对ILogger的Log方法传参结构理解有误。
失败原因说明
ILogger的Log方法第三个参数为内部的FormattedLogValues类型,该类型实现了IReadOnlyList<KeyValuePair<string, object>>接口,直接调用ToString()会返回类型名称而非实际日志内容,因此你的匹配逻辑无法命中。
正确实现示例
方案1:直接匹配状态对象内容
_logger.IsEnabled(Arg.Any<LogLevel>()).Returns(true); _logger.Received().Log( Arg.Any<LogLevel>(), Arg.Any<EventId>(), Arg.Is<object>(o => ((IReadOnlyList<KeyValuePair<string, object>>)o) .Any(kv => kv.Value?.ToString()?.Contains("bad") == true) ), Arg.Any<Exception>(), Arg.Any<Func<object, Exception, string>>() );
方案2:通过格式化委托获取完整日志文本匹配
如果需要匹配最终输出的完整日志字符串,可以调用Log方法传入的格式化委托生成文本后再匹配:
var receivedCalls = _logger.ReceivedCalls() .Where(call => call.GetMethodInfo().Name == nameof(ILogger.Log)) .Select(call => call.GetArguments()) .ToList(); Assert.IsTrue(receivedCalls.Any(args => { var logLevel = (LogLevel)args[0]; var state = args[2]; var exception = (Exception)args[3]; var formatter = (Func<object, Exception, string>)args[4]; var logContent = formatter(state, exception); return logLevel == LogLevel.Error && logContent.Contains("bad"); }));
内容的提问来源于stack exchange,提问作者AdvancingEnemy
相关产品推荐
相关产品推荐

