You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请问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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 12:36:03