如何在abp.io框架测试场景下模拟ObjectMapper实例
解决方案
核心思路:ABP框架的ApplicationService依赖的是IObjectMapper接口而非具体实现类,直接用NSubstitute模拟该接口的对应方法即可,无需构造真实的ObjectMapper实例。
实现步骤
- 第一步:创建
IObjectMapper的模拟实例
var mockObjectMapper = Substitute.For<IObjectMapper>();
- 第二步:配置
Map方法的返回规则,匹配你业务中用到的泛型类型
// 配置 classFrom 转 classTo 的映射返回 var expectedTarget = new classTo { // 填充你需要的返回属性值 Id = 1, Name = "TestData" }; mockObjectMapper.Map<classFrom, classTo>(Arg.Any<classFrom>()).Returns(expectedTarget); // 如果用到了非泛型重载,可以同步配置 mockObjectMapper.Map(Arg.Any<Type>(), Arg.Any<Type>(), Arg.Any<object>()).Returns(expectedTarget); // 如果用到了覆盖已有对象的重载,也可以单独配置 mockObjectMapper.Map<classFrom, classTo>(Arg.Any<classFrom>(), Arg.Any<classTo>()) .Returns((classFrom s, classTo t) => { t.Id = s.Id; t.Name = s.Name; return t; });
- 第三步:将模拟实例注入到依赖容器
如果是直接构造ApplicationService实例,直接给属性赋值即可:
var yourAppService = new YourApplicationService() { ObjectMapper = mockObjectMapper, // 其他依赖可同步赋值 LazyServiceProvider = Substitute.For<ILazyServiceProvider>() };
如果是通过LazyServiceProvider提供依赖,按以下方式注册:
var mockLazyProvider = Substitute.For<ILazyServiceProvider>(); mockLazyProvider.GetService<IObjectMapper>().Returns(mockObjectMapper); var yourAppService = new YourApplicationService() { LazyServiceProvider = mockLazyProvider };
完整测试示例
using NSubstitute; using Volo.Abp.ObjectMapping; using Xunit; public class ProductAppServiceTests { [Fact] public void GetProduct_Returns_Correct_Dto() { // 模拟ObjectMapper var mockMapper = Substitute.For<IObjectMapper>(); var expectedDto = new ProductDto { Id = 1001, ProductName = "测试商品", Price = 99.9 }; mockMapper.Map<Product, ProductDto>(Arg.Any<Product>()).Returns(expectedDto); // 构造应用服务实例 var productAppService = new ProductAppService() { ObjectMapper = mockMapper, // 模拟仓储等其他依赖 Repository = Substitute.For<IRepository<Product, Guid>>() }; productAppService.Repository.GetAsync(Arg.Any<Guid>()).Returns(new Product { Id = Guid.NewGuid() }); // 执行测试方法 var result = productAppService.GetAsync(Guid.NewGuid()); // 结果断言 Assert.Equal(expectedDto.Id, result.Id); // 验证映射方法确实被调用 mockMapper.Received(1).Map<Product, ProductDto>(Arg.Any<Product>()); } }
注意:NSubstitute不会自动匹配不同的方法重载,如果你用到了
IObjectMapper的多个重载,需要逐个对用到的重载做返回配置。
内容的提问来源于stack exchange,提问作者Terry
相关产品推荐
相关产品推荐

