如何用FakeItEasy模拟抽象类公共方法返回不同值或抛异常
用FakeItEasy模拟抽象类方法的单元测试方案
当然可以通过FakeItEasy实现对抽象类公共方法的模拟,不管是让方法返回指定结果还是抛出异常都能轻松完成。以下是针对你提供的代码的具体测试实现方案:
先修正原代码的两处问题
Worker类中的provate拼写错误,应改为privateHandler方法需改为async Task类型,否则无法正确等待异步方法DoTaskAsync的执行,测试逻辑会失效
测试场景1:模拟服务方法正常执行
[Fact] public async Task WorkerHandler_WhenServiceExecutesSuccessfully_CompletesNormally() { // Arrange // 创建Fake的抽象类实例 var fakeService = A.Fake<ServiceBases>(); // 配置DoTaskAsync方法正常完成(返回已完成的Task) A.CallTo(() => fakeService.DoTaskAsync(A<object>._)) // 替换...为实际参数类型 .Returns(Task.CompletedTask); // 模拟IServiceProvider,让它返回我们的Fake服务 var fakeServiceProvider = A.Fake<IServiceProvider>(); var testOrder = new Order { Properties = new OrderProperties { Type = typeof(ServiceBases) } }; A.CallTo(() => fakeServiceProvider.GetService(testOrder.Properties.Type)) .Returns(fakeService); // 模拟ILogger var fakeLogger = A.Fake<ILogger>(); // 实例化待测试的Worker var worker = new Worker(fakeLogger, fakeServiceProvider); // Act await worker.Handler(testOrder); // Assert // 验证DoTaskAsync方法确实被调用了一次 A.CallTo(() => fakeService.DoTaskAsync(A<object>._)) .MustHaveHappenedOnceExactly(); }
测试场景2:模拟服务方法抛出异常
[Fact] public async Task WorkerHandler_WhenServiceThrowsException_HandlesError() { // Arrange var testException = new InvalidOperationException("测试异常"); var fakeService = A.Fake<ServiceBases>(); // 配置DoTaskAsync方法抛出指定异常 A.CallTo(() => fakeService.DoTaskAsync(A<object>._)) .ThrowsAsync(testException); var fakeServiceProvider = A.Fake<IServiceProvider>(); var testOrder = new Order { Properties = new OrderProperties { Type = typeof(ServiceBases) } }; A.CallTo(() => fakeServiceProvider.GetService(testOrder.Properties.Type)) .Returns(fakeService); var fakeLogger = A.Fake<ILogger>(); var worker = new Worker(fakeLogger, fakeServiceProvider); // Act & Assert // 验证调用Handler时会抛出对应的异常(如果Worker未捕获异常) var thrownException = await Assert.ThrowsAsync<InvalidOperationException>( () => worker.Handler(testOrder)); Assert.Equal(testException.Message, thrownException.Message); // 如果Worker内部捕获异常并记录日志,验证日志方法是否被调用 A.CallTo(() => fakeLogger.LogError(A<Exception>._, A<string>._)) .MustHaveHappened(); }
关键注意点
- 模拟异步方法时,用
Returns(Task.CompletedTask)表示无返回值的异步方法正常完成;如果是带返回值的async Task<T>方法,使用ReturnsAsync(指定返回值)即可。 - 异步方法抛出异常必须用
ThrowsAsync(exception),而非同步方法的Throws,否则无法正确模拟异步异常的抛出逻辑。 - 确保
IServiceProvider.GetService的模拟参数与测试用Order的Type一致,这样才能正确返回我们预先配置的Fake服务实例。
内容的提问来源于stack exchange,提问作者susanna
相关产品推荐
相关产品推荐

