如何用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
相关产品推荐
相关产品推荐

