You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用FakeItEasy模拟抽象类公共方法返回不同值或抛异常

用FakeItEasy模拟抽象类方法的单元测试方案

当然可以通过FakeItEasy实现对抽象类公共方法的模拟,不管是让方法返回指定结果还是抛出异常都能轻松完成。以下是针对你提供的代码的具体测试实现方案:

先修正原代码的两处问题

  1. Worker类中的provate拼写错误,应改为private
  2. Handler方法需改为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 08:02:02