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

如何为使用AutoMapper的ServiceStack服务编写单元测试?

ServiceStack单元测试中AutoMapping映射的解决方案

核心问题分析

ServiceStack的AutoMapping是全局静态的映射系统,而非依赖注入的实例组件,所以单元测试中无需“注入”映射器,只需在测试执行前完成转换器注册,就能让服务中的映射逻辑正常工作。

具体解决方案步骤

1. 在测试初始化阶段注册映射规则

在测试类的初始化方法中调用你的映射注册逻辑,确保全局转换规则生效:

  • 若使用xUnit,可在测试类构造函数中执行注册
  • 若使用NUnit,可在[SetUp]方法中执行

2. 修正测试类中的实例化错误

你的测试代码里存在构造函数错误:_sut = new OrderApiRepository(orderApiRepository);,应该实例化服务类OrderApiService而非仓库类。

3. 验证映射逻辑的执行

确保服务中使用ServiceStack的ConvertTo<T>方法或自动映射逻辑,这些会自动调用全局注册的转换器。

修正后的xUnit测试代码示例

using AutoMapper;
using FluentAssertions;
using NSubstitute;

namespace Api.Services.Tests.Unit;

public class OrderApiServiceTests
{
    private readonly OrderApiService _sut;
    private readonly IOrderApiRepository _orderApiRepository = Substitute.For<IOrderApiRepository>();

    public OrderApiServiceTests()
    {
        // 注册ServiceStack全局映射转换器
        ApiDtoMapping.Register();
        // 正确实例化服务类
        _sut = new OrderApiService(_orderApiRepository);
    }

    [Fact]
    public async Task Get_ShouldReturnAccount_WhenAccountExistsAsync()
    {
        // Arrange
        var order = new Order
        {
            Name = "MyOrder",
            Value = 1000,
        };

        var expectedResponse = new OrderApiDto
        {
            Name = "MyOrder",
            Value = 1000,
        };

        _orderApiRepository.GetAsync(Arg.Any<GetOrder>()).Returns(order);

        // Act
        var result = await _sut.Get(new GetOrder());

        // Assert
        result.StatusCode.Should().Be(System.Net.HttpStatusCode.OK);
        result.Response.Should().BeEquivalentTo(expectedResponse);
    }
}

NUnit版本测试示例(对应完整项目)

using NSubstitute;
using NUnit.Framework;
using ssUnitTests.ServiceInterface;
using ssUnitTests.ServiceModel;

namespace ssUnitTests.Tests;

public class UnitTest
{
    private readonly MyServices _sut;
    private readonly IOrderRepository _repository = Substitute.For<IOrderRepository>();

    [SetUp]
    public void Setup()
    {
        // 注册全局映射转换器
        Mappings.RegisterConverters();
        _sut = new MyServices(_repository);
    }

    [Test]
    public void Get_ShouldReturn_OrderDto()
    {
        var order = new Order
        {
            Name = "MyName",
            BaseProperty = "MyBaseProperty"
        };

        _repository.GetOrder().Returns(order);

        var response = (OrderDto)_sut.Any(new OrderRequest { Id = 1 });

        Assert.That(response.Name.Equals(order.Name));
        Assert.That(response.DtoProperty.Equals(order.BaseProperty + "Dto"));
    }
}

关键说明

  • ServiceStack的AutoMapping.RegisterConverter()注册的是全局类型转换规则,所有后续的ConvertTo<T>调用都会遵循这些规则
  • 单元测试中无需注入IMapper实例,只要确保服务执行前完成注册即可
  • 若担心全局状态污染,可在测试结束的清理方法(如NUnit的[TearDown])中重新初始化映射规则(ServiceStack暂无官方清理方法,需自行重置相关静态状态)

内容的提问来源于stack exchange,提问作者Samuel Wahlberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:50:43