如何从Task中正确抛出异常?Assert.ThrowsAsync未捕获预期异常
问题原因与解决方案
问题出在你使用ContinueWith处理异步任务的方式上:
ContinueWith属于传统TPL(任务并行库)API,它不会像async/await那样自动解包任务的内部异常。当你在ContinueWith的委托中访问entityTask.Result时,无论上游任务抛出异常,还是你主动抛出UnauthorizedAccessException,最终都会被封装在ContinueWith返回任务的AggregateException内部。Assert.ThrowsAsync只会捕获直接抛出的目标异常,不会自动解包AggregateException的内部异常。
修正后的代码
把Read方法改为使用async/await语法,它会自动处理异常解包:
public async Task<TEntity> Read<TEntity>(object id) where TEntity : class { var entity = await InternalRead<TEntity>(id); if (entity != null && !entity.IsHidden) throw new UnauthorizedAccessException(); return entity; }
同时修正InternalRead的泛型参数混用问题:
protected override async Task<TEntity> InternalRead<TEntity>(object id) { var result = await context.Set<TEntity>().FindAsync(id); return result; }
测试代码修正
确保测试方法调用的参数与方法定义一致(原代码中Read调用传了两个参数,但方法定义仅接收id,需对齐):
[Fact] public async Task InvalidIdThrowsExpectedException() { var db = /* 你的数据库实例代码 */; await Assert.ThrowsAsync<UnauthorizedAccessException>(() => accessor.Read<TradingStyle>(1)); }
修改后,Assert.ThrowsAsync就能正确捕获到你抛出的UnauthorizedAccessException,不会再出现AggregateException包装的问题。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

