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

如何用NSubstitute对同签名方法先抛异常后返回值?

解决NSubstitute同一参数方法首次抛异常、后续返回值的问题

首先得说下你当前配置的问题:你先给所有Get调用(Arg.Any<string>())设置了抛NotFoundException,然后用When...Do的方式试图修改特定参数的行为,但这个Do块里的代码会在第一次调用Get("id1")的时候立即执行——相当于第一次调用时就把Get("id1")的行为改成了返回MyDto,所以自然不会抛出异常。

要实现「同一参数首次调用抛异常,后续调用返回值」的需求,NSubstitute有更直接、更可靠的写法,不需要绕When...Do,推荐两种方式:

方式一:链式调用Throws和Returns

针对特定参数,先指定抛出异常,再通过AndDoes在第一次调用后修改后续行为:

IMyRepository _repository = Substitute.For<IMyRepository>();
var myAction = new MyAction(_repository);

// 针对"id1"这个参数,首次调用抛异常,之后调用返回MyDto
_repository.Get("id1")
    .Throws<NotFoundException>()
    .AndDoes(_ => _repository.Get("id1").Returns(new MyDto()));

方式二:使用Returns的多结果重载

NSubstitute的Returns方法支持传入多个返回逻辑,调用时会按顺序依次执行:第一次用第一个逻辑,第二次及以后用第二个:

IMyRepository _repository = Substitute.For<IMyRepository>();
var myAction = new MyAction(_repository);

// 首次调用抛NotFoundException,第二次及以后返回MyDto
_repository.Get(Arg.Is<string>(r => r == "id1"))
    .Returns(
        _ => throw new NotFoundException(),  // 第一次调用的行为
        _ => new MyDto()                     // 第二次及以后调用的行为
    );

为什么这个写法有效?

这个重载会为同一匹配规则的调用维护一个执行序列,每次调用都会取下一个预先定义的行为,完美贴合你需要的「首次抛异常,后续返回值」场景,而且代码简洁直观,不容易出错。

另外要注意:如果你之前设置过Arg.Any<string>()的全局行为,NSubstitute会优先匹配更具体的参数规则(比如Arg.Is("id1")比Arg.Any<string>()优先级更高),所以只要你先配置特定参数的序列行为,就不会和全局规则冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 09:52:44