如何为ContinueWith编写单元测试?Xunit+NSubstitute遇IsFaulted覆盖难题
测试Task.IsFaulted分支的Xunit+NSubstitute用例
要覆盖task.IsFaulted分支,核心是让_service.GetProfile(code)返回一个处于Faulted状态的Task,以下是具体实现步骤和测试用例:
1. 明确被测方法结构(假设)
先把业务代码封装到可测试的方法中,示例如下:
public class ProfileHandler { private readonly IProfileService _service; public ProfileHandler(IProfileService service) { _service = service; } public async Task<object> GetProfileResponse(string code) { var response = await await _service.GetProfile(code) .ContinueWith(async task => { if (task.IsFaulted) { // 待覆盖的错误分支逻辑,示例返回默认对象 return new object(); } // 正常分支逻辑(示例) var profile = await task; return profile; }); return response; } } // 定义服务接口 public interface IProfileService { Task<Profile> GetProfile(string code); } public class Profile { }
2. 编写Xunit测试用例
通过NSubstitute模拟IProfileService,让GetProfile返回Faulted状态的Task:
using Xunit; using NSubstitute; public class ProfileHandlerTests { [Fact] public async Task GetProfileResponse_WhenGetProfileFails_ExecutesFaultedBranch() { // 1. 准备模拟依赖 var mockService = Substitute.For<IProfileService>(); // 创建Faulted状态的Task,模拟服务调用失败 var faultedTask = Task.FromException<Profile>(new InvalidOperationException("模拟服务调用出错")); mockService.GetProfile(Arg.Any<string>()).Returns(faultedTask); // 2. 实例化被测对象 var handler = new ProfileHandler(mockService); // 3. 执行被测方法 var result = await handler.GetProfileResponse("test-code"); // 4. 验证分支逻辑执行结果(根据实际需求调整断言) Assert.NotNull(result); // 如果错误分支中有其他操作(如日志记录),可在此验证: // mockLogger.Received(1).LogError(Arg.Any<Exception>(), Arg.Any<string>()); } }
关键说明
- 用
Task.FromException<TResult>()直接创建Faulted状态的Task,这是触发task.IsFaulted的核心。 - 无需手动抛出异常,
GetProfile返回的Task本身已处于错误状态,ContinueWith会自动检测到task.IsFaulted为true。 - 如果
GetProfile返回无返回值的Task(而非Task<T>),则用Task.FromException(new Exception(...))创建Faulted Task。
内容的提问来源于stack exchange,提问作者Jonathas Souza
相关产品推荐
相关产品推荐

