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

NSubstitute Mock带params参数方法返回集合为空如何正确配置

NSubstitute Mock带params参数方法返回值异常解决方案

问题复现

TestClass类定义的方法签名如下:

public virtual async Task<IEnumerable<T>> GetAll(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes)

原有Mock配置代码可正常编译,但调用时返回空集合,未返回预设的2个Animal对象:

_testClass.GetAll(Arg.Any<Expression<Func<Animal, bool>>>()).Returns(new List<Animal>(){new Animal(), new Animal()});

根因分析

NSubstitute的参数匹配是严格按参数列表执行的。原配置只匹配了仅传入1个predicate参数的调用,但C#中params参数的本质是语法糖,即使调用时不显式传值,编译器也会自动传入一个空数组作为第二个参数。因此实际调用时参数个数为2,和配置的单参数规则不匹配,NSubstitute会返回IEnumerable<Animal>的默认值(空序列),导致返回集合长度为0。

正确配置方式

通用场景:匹配所有调用(无论是否传includes参数)

补充第二个params数组的任意匹配规则即可,这是最常用的配置方式:

_testClass.GetAll(
        Arg.Any<Expression<Func<Animal, bool>>>(),
        Arg.Any<Expression<Func<Animal, object>>[]>()
    )
    .Returns(new List<Animal> { new Animal(), new Animal() });

若使用较低版本NSubstitute,不支持自动将同步值包装为Task返回,可显式返回Task包装结果:

.Returns(Task.FromResult<IEnumerable<Animal>>(new List<Animal> { new Animal(), new Animal() }));

精确场景:仅匹配不传includes参数的调用

如果需要精确匹配未传入任何includes参数(即第二个参数为空数组)的场景,可使用Arg.Is做条件匹配:

_testClass.GetAll(
        Arg.Any<Expression<Func<Animal, bool>>>(),
        Arg.Is<Expression<Func<Animal, object>>[]>(arr => arr.Length == 0)
    )
    .Returns(new List<Animal> { new Animal(), new Animal() });

注意事项

  • 如果存在传入1个或多个includes参数的调用场景,需要单独为对应参数数量的调用配置返回规则,否则仍会返回空序列
  • params是C#的编译期语法糖,对Mock框架而言和普通数组参数没有区别,必须显式配置匹配规则

内容的提问来源于stack exchange,提问作者Sike12

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 04:51:30