如何用同一FakeManager编写C#单元测试覆盖try-catch分支
解决方案:给Fake类添加可控的行为开关
你可以给ManagerFake添加一个可配置的属性,用来控制它的GetRequest方法是正常返回还是抛出异常。这样同一个Fake类就能覆盖两种测试场景,满足代码覆盖率要求。
步骤1:修改ManagerFake类,添加行为控制开关
首先更新你的Fake实现,加入一个布尔属性来决定是否抛出异常:
public class ManagerFake : IManager { // 新增:控制是否抛出异常的开关 public bool ShouldThrowException { get; set; } public Task GetRequest() { if (ShouldThrowException) { // 抛出你需要测试的异常类型,比如InvalidOperationException throw new InvalidOperationException("模拟异常场景"); } // 正常场景返回Task.FromResult return Task.FromResult(true); } }
步骤2:编写两种场景的单元测试
在测试代码里,你只需要在不同的测试用例中设置ShouldThrowException的取值,就能分别覆盖try块和catch块的逻辑:
测试正常场景(覆盖try块)
[Test] public async Task GetRequest_WhenCalled_ReturnsOk() { // 1. 准备Fake实例,设置为不抛出异常 var fakeManager = new ManagerFake { ShouldThrowException = false }; // 2. 注入Fake到控制器 var controller = new MyControllerClass(fakeManager); // 3. 执行测试方法 var result = await controller.GetRequest(); // 4. 断言结果是否符合预期 Assert.IsInstanceOf<OkResult>(result); }
测试异常场景(覆盖catch块)
[Test] public void GetRequest_WhenManagerThrowsException_ThrowsHttpResponseException() { // 1. 准备Fake实例,设置为抛出异常 var fakeManager = new ManagerFake { ShouldThrowException = true }; // 2. 注入Fake到控制器 var controller = new MyControllerClass(fakeManager); // 3. 执行测试并断言是否抛出目标异常 Assert.ThrowsAsync<HttpResponseException>(async () => await controller.GetRequest()); }
额外优化提示
如果你需要模拟不同类型的异常,可以扩展这个Fake类,比如添加一个ExceptionToThrow属性,直接指定要抛出的异常实例,灵活性更高:
public Exception ExceptionToThrow { get; set; } public Task GetRequest() { if (ExceptionToThrow != null) { throw ExceptionToThrow; } return Task.FromResult(true); }
这样在测试里可以指定任意异常类型,比如:
fakeManager.ExceptionToThrow = new TimeoutException("模拟超时异常");
另外注意修正你原代码里的小笔误:pubic应该是public,this.ok()应该是this.Ok(),throw this.HTTPResponseException应该是throw new HttpResponseException(...)(对应ASP.NET Web API的标准异常类型)。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

