如何Mock抛出含入参异常消息的异步方法?
问题
在Mock包含Task<List<int>> GetIdsAsync(int)方法的ISomething接口时,已实现通过入参生成返回值:
mock.Setup(x => x.GetIdsAsync(It.IsAny<int>())) .ReturnsAsync((int n) => new List<int>(n));
也能Mock该方法抛出固定异常:
mock.Setup(x => x.GetIdsAsync(It.IsAny<int>())) .ThrowsAsync(new InvalidOperationException());
但希望抛出包含入参的异常:throw new InvalidOperationException($"{n} is not valid");,即使用入参生成异常消息。尝试了以下写法:
mock.Setup(x => x.GetIdsAsync(It.IsAny<int>())) .ThrowsAsync((int n) => new InvalidOperationException($"{n} is not valid"));
但出现报错:
CS1929 'ISetup<ISomething, Task<List<int>>>' does not contain a definition for 'ThrowsAsync' and the best extension method overload 'SequenceExtensions.ThrowsAsync(ISetupSequentialResult<Task>, Exception)' requires a receiver of type 'ISetupSequentialResult<Task>'
请问正确的语法应该是什么?
解决方案
有两种正确写法可以实现需求:
方法一:利用ReturnsAsync手动抛出异常
异步方法的ReturnsAsync支持传入带参数的委托,可在委托内直接抛出目标异常:
mock.Setup(x => x.GetIdsAsync(It.IsAny<int>())) .ReturnsAsync((int n) => { throw new InvalidOperationException($"{n} is not valid"); });
方法二:使用Throws结合参数委托
对于异步方法,Moq的Throws方法支持接受带参数的委托,会自动处理异步场景下的异常抛出逻辑:
mock.Setup(x => x.GetIdsAsync(It.IsAny<int>())) .Throws((int n) => new InvalidOperationException($"{n} is not valid"));
报错原因:ThrowsAsync的重载仅支持直接传入异常实例,或用于顺序Mock场景,不支持通过带参数的委托动态生成异常。上述两种写法利用了支持参数委托的ReturnsAsync或Throws方法,实现了根据入参生成异常消息的需求。
内容的提问来源于stack exchange,提问作者Mr. Boy
相关产品推荐
相关产品推荐

