如何为使用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
相关产品推荐
相关产品推荐

