.NET下用xUnit和NSubstitute测试AutoMapper解析器报错求助
解决AutoMapper解析器无参构造函数缺失的单元测试问题
你的UnitImgUrlResolver依赖IAzureBlobStorageService且未定义无参构造函数,AutoMapper默认无法自动实例化该解析器,因此抛出错误。以下是两种可行的测试解决方案:
方法一:手动传入带Mock依赖的解析器实例
直接在测试的Mapper配置中创建解析器实例,传入Mock的IAzureBlobStorageService:
public class AutoMapperTests { private readonly IMapper _mapper; private readonly IAzureBlobStorageService _mockBlobService; public AutoMapperTests() { // 创建Mock服务并预设返回值 _mockBlobService = Substitute.For<IAzureBlobStorageService>(); _mockBlobService.UploadImageToBlobStorage(Arg.Any<IFormFile>(), Arg.Any<string>()) .Returns("MockedImageUrl"); var config = new MapperConfiguration(cfg => { // 直接配置映射并传入解析器实例 cfg.CreateMap<UnitPostVModel, UnitBLLModel>() .ForMember(dest => dest.imgUrl, opt => opt.MapFrom(new UnitImgUrlResolver(_mockBlobService))); // 若需保留原有Profile,可先加载Profile再覆盖该成员配置 // cfg.AddProfile<AutoMapperProfile>(); // cfg.CreateMap<UnitPostVModel, UnitBLLModel>() // .ForMember(dest => dest.imgUrl, opt => opt.MapFrom(new UnitImgUrlResolver(_mockBlobService))); }); _mapper = config.CreateMapper(); } [Fact] public void Should_Map_UnitPostVModel_To_UnitBLLModel() { // Arrange var unitPostVModel = new UnitPostVModel { abbreviation = "A", name = "Test" // 如需测试带图片的场景,可添加image对象 // image = new FormFile(new MemoryStream(), 0, 0, "test", "test.jpg") }; // Act var result = _mapper.Map<UnitBLLModel>(unitPostVModel); // Assert Assert.NotNull(result); // 当src.image为null时,解析器返回空字符串,需对应调整断言 // Assert.Equal(string.Empty, result.imgUrl); // 当测试带图片场景时,断言Mock的返回值 // Assert.Equal("MockedImageUrl", result.imgUrl); // 验证Mock方法是否被调用 // _mockBlobService.Received(1).UploadImageToBlobStorage(Arg.Any<IFormFile>(), Arg.Any<string>()); } }
方法二:通过ServiceProvider注入依赖
利用依赖注入容器注册Mock服务,让AutoMapper自动解析解析器的依赖,更贴近实际项目的DI模式:
public class AutoMapperTests { private readonly IMapper _mapper; private readonly IAzureBlobStorageService _mockBlobService; public AutoMapperTests() { // 创建Mock服务并预设返回值 _mockBlobService = Substitute.For<IAzureBlobStorageService>(); _mockBlobService.UploadImageToBlobStorage(Arg.Any<IFormFile>(), Arg.Any<string>()) .Returns("MockedImageUrl"); // 构建ServiceProvider并注册服务 var serviceProvider = new ServiceCollection() .AddSingleton(_mockBlobService) .AddAutoMapper(cfg => cfg.AddProfile<AutoMapperProfile>()) .BuildServiceProvider(); // 从容器获取配置好的Mapper实例 _mapper = serviceProvider.GetRequiredService<IMapper>(); } [Fact] public void Should_Map_UnitPostVModel_To_UnitBLLModel() { // Arrange var unitPostVModel = new UnitPostVModel { abbreviation = "A", name = "Test" }; // Act var result = _mapper.Map<UnitBLLModel>(unitPostVModel); // Assert Assert.NotNull(result); Assert.Equal(string.Empty, result.imgUrl); // 无图片时返回空字符串 // 若测试带图片场景,断言Mock返回值并验证方法调用 // Assert.Equal("MockedImageUrl", result.imgUrl); // _mockBlobService.Received(1).UploadImageToBlobStorage(Arg.Any<IFormFile>(), Arg.Any<string>()); } }
注意事项
- 当
src.image为null时,解析器返回空字符串,需对应调整断言内容; - 方法一适合快速测试单个映射规则,方法二更适合验证完整的Profile配置;
- 测试带图片的场景时,需构造有效的
IFormFile对象,并验证Mock服务的方法调用情况。
内容的提问来源于stack exchange,提问作者Lucia
相关产品推荐
相关产品推荐

