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

ABP.io单元测试中LocalIocManager的替代方案咨询

在ABP.io中简化单元测试的依赖替换方案

核心思路:利用ABP测试基类的服务替换能力

ABP.io的测试框架内置了对依赖注入容器的操作能力,无需手动逐个构造待测试实例并注入依赖。通过测试基类提供的配置方法,你可以批量替换或模拟所需服务,让DI容器自动完成其余依赖的注入。

具体实现步骤

1. 继承对应测试基类

根据要测试的组件类型,继承合适的测试基类:

  • 测试领域服务:DomainTestBase<TModule>
  • 测试应用服务:ApplicationTestBase<TModule>
    这些基类会自动初始化测试专用的DI容器。

2. 重写ConfigureServices替换依赖

在测试类中重写基类的ConfigureServices方法,结合NSubstitute创建模拟实例,并用容器的扩展方法替换原有服务注册:

public class OrderManagerTest : DomainTestBase<MyShopDomainModule>
{
    private IOrderManager _orderManager;
    private IOrderRepository _fakeOrderRepo;
    private IInventoryService _fakeInventoryService;

    protected override void ConfigureServices(ServiceConfigurationContext context)
    {
        // 创建模拟依赖
        _fakeOrderRepo = Substitute.For<IOrderRepository>();
        _fakeInventoryService = Substitute.For<IInventoryService>();

        // 替换容器中已注册的服务实现
        context.Services.Replace(ServiceDescriptor.Transient<IOrderRepository>(_ => _fakeOrderRepo));
        context.Services.Replace(ServiceDescriptor.Transient<IInventoryService>(_ => _fakeInventoryService));
    }

    [SetUp]
    public void Setup()
    {
        // 从测试容器中获取待测试的服务实例
        _orderManager = GetRequiredService<IOrderManager>();
    }

    [Test]
    public async Task Should_Create_Order_When_Inventory_Available()
    {
        // 配置模拟服务的返回逻辑
        _fakeInventoryService.IsStockAvailableAsync(Arg.Any<Guid>()).Returns(true);
        _fakeOrderRepo.InsertAsync(Arg.Any<Order>()).Returns(Task.CompletedTask);

        // 执行测试方法
        var result = await _orderManager.CreateOrderAsync(Guid.NewGuid(), 10);

        // 断言验证
        Assert.IsTrue(result.Success);
        await _fakeOrderRepo.Received(1).InsertAsync(Arg.Any<Order>());
    }
}

3. 封装通用替换逻辑(可选)

如果多个测试类需要替换相同的依赖,可以自定义测试基类来复用逻辑:

public class CustomDomainTestBase<TModule> : DomainTestBase<TModule>
{
    protected IOrderRepository FakeOrderRepo { get; private set; }

    protected override void ConfigureServices(ServiceConfigurationContext context)
    {
        base.ConfigureServices(context);
        
        FakeOrderRepo = Substitute.For<IOrderRepository>();
        context.Services.Replace(ServiceDescriptor.Transient<IOrderRepository>(_ => FakeOrderRepo));
    }
}

后续测试类直接继承这个自定义基类即可:

public class OrderManagerTest : CustomDomainTestBase<MyShopDomainModule>
{
    private IOrderManager _orderManager;

    [SetUp]
    public void Setup()
    {
        _orderManager = GetRequiredService<IOrderManager>();
    }

    // ...测试方法
}

关键优势

  • 无需手动构造复杂的待测试实例,DI容器自动处理未替换的依赖
  • 集中管理依赖替换逻辑,依赖数量多时仍能保持代码整洁
  • 完全兼容NSubstitute等模拟框架,保留原有测试习惯

内容的提问来源于stack exchange,提问作者Damien R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 05:50:27