NSubstitute如何实现每次方法调用触发随机延迟返回新结果
问题根源
当前实现不符合预期的核心原因有两个:
- 你向
Returns()传入的是一个预先构造完成的Task实例,NSubstitute会将这个固定值缓存为方法的返回结果。首次调用等待该任务完成后,后续所有调用都会直接返回这个已完成的任务,不会重新触发延迟逻辑。 fixture.Create<DiscosObject>()的调用写在了Mock客户端的初始化块中,只会在创建IDiscosClient实例时执行一次,后续调用不可能返回新的模型对象。
修复方案
使用Returns()的委托重载,将延迟计算、对象生成的逻辑全部包裹在委托内部。这样每次调用GetSingle<T>()方法时,都会重新执行委托逻辑,生成新的随机延迟、返回新的模型实例。
修正后的代码如下:
Fixture fixture = new(); fixture.Customize(new DiscosModelFixtureCustomizationNoLinks()); builder.Services.AddTransient(_ => { IDiscosClient client = Substitute.For<IDiscosClient>(); client.GetSingle<DiscosObject>(Arg.Any<string>()) .Returns(async () => { // 每次调用生成新的随机延迟时长 int delay = Random.Shared.Next(1000, 5000); await Task.Delay(delay); // 每次调用返回全新生成的模型对象 return fixture.Create<DiscosObject>(); }); return client; });
这个实现不需要引入额外依赖,仅用NSubstitute原生功能就可以满足需求:
- 同个Mock实例的每次调用都会触发独立的1-5秒随机延迟
- 延迟结束后返回全新生成的
DiscosObject实例,不会复用历史返回值 - 用async/await写法替代原有
ContinueWith,逻辑更清晰,也避免了任务延续的异常捕获问题。
内容的提问来源于stack exchange,提问作者ScottishTapWater
相关产品推荐
相关产品推荐

