【发布时间】:2019-08-31 11:18:39
【问题描述】:
我在 .NET Core 中有一个项目,我正在使用 AutoMapper 在我的类型之间进行映射。但是我遇到了一个问题,我想模拟我的自定义值解析器的参数。我创建了虚拟示例来显示问题:
假设我有一个 ValueResolver,它需要访问 DB 来解析给定的成员:
public class NumberProfile : Profile
{
public NumberProfile()
{
CreateMap<NumberModel, NumberDto>()
.ForMember(dest => dest.Number, opt => opt.MapFrom<NumberValueResolver>());
}
}
public class NumberValueResolver : IValueResolver<NumberModel, NumberDto, int>
{
private readonly IRepository _repository;
public NumberValueResolver(IRepository repository)
{
_repository = repository;
}
public int Resolve(NumberModel source, NumberDto destination, int destMember, ResolutionContext context)
{
return _repository.GetNumber().Number + 3;
}
}
让我们想象一下,Resolve 方法中有逻辑需要测试,我想模拟存储库以对其进行测试。 这是我在测试中尝试过的
var repositoryMock = new Mock<IRepository>();
repositoryMock.Setup(s => s.GetNumber()).Returns(new NumberModel { Number = 3 });
var mapper = new MapperConfiguration(mc =>
{
mc.AddProfile<NumberProfile>();
mc.ConstructServicesUsing(s => new NumberValueResolver(repositoryMock.Object));
});
var service = new Service(repositoryMock.Object, mapper.CreateMapper());
然后我在服务上调用一个方法来触发映射。 这个案例很好,它有效并且测试通过了。当我添加另一个 ValueResolver 时,问题就来了。
public class NumberProfile : Profile
{
public NumberProfile()
{
CreateMap<NumberModel, NumberDto>()
.ForMember(dest => dest.Number, opt => opt.MapFrom<NumberValueResolver>())
.ForMember(dest => dest.AnotherNumber, opt => opt.MapFrom<AnotherNumberValueResolver>());
}
}
public class NumberValueResolver : IValueResolver<NumberModel, NumberDto, int>
{
private readonly IRepository _repository;
public NumberValueResolver(IRepository repository)
{
_repository = repository;
}
public int Resolve(NumberModel source, NumberDto destination, int destMember, ResolutionContext context)
{
return _repository.GetNumber().Number + 3;
}
}
public class AnotherNumberValueResolver : IValueResolver<NumberModel, NumberDto, string>
{
public int Resolve(NumberModel source, NumberDto destination, string destMember, ResolutionContext context)
{
return $"{source.Number} number(s)";
}
}
然后我想我会在我的测试中这样做
var repositoryMock = new Mock<IRepository>();
repositoryMock.Setup(s => s.GetNumber()).Returns(new NumberModel { Number = 3 });
var mapper = new MapperConfiguration(mc =>
{
mc.AddProfile<NumberProfile>();
mc.ConstructServicesUsing(s => new NumberValueResolver(repositoryMock.Object));
mc.ConstructServicesUsing(s => new AnotherNumberValueResolver());
});
var service = new Service(repositoryMock.Object, mapper.CreateMapper());
然后我得到错误:
System.InvalidCastException:无法将“AutoMapper_app.ValueResolvers.AnotherNumberValueResolver”类型的对象转换为“AutoMapper_app.ValueResolvers.NumberValueResolver”类型。
我是否误解了 ConstructServicesUsing 或 ValueResolvers 的用法,还是完全不同?我错过了一些非常明显的东西吗?是不是设计不好?
【问题讨论】:
-
您接收要创建的类型作为参数。
-
抱歉,不知道你的意思。
标签: c# unit-testing .net-core automapper moq