我正在尝试在 xunit 上使用 moq 创建一个单元测试,但是测试失败了,我客人是因为映射器,当调用
_sut.Create
时,如果我删除 MockBehavior.Strict
行为 _sut.Create
,它会抛出异常
返回 0 而不是 1。
我该如何解决这个问题?谢谢您的想法。
_logger = new Mock<ILogger<BaseCRUDDomainService<ClientDTO, client>>>().Object;
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new DomainMapper());
});
_mapper = mockMapper.CreateMapper();
var mockRepository = new Mock<IBaseCRUDRepository<client>>(MockBehavior.Strict);
//reponse create 1
var clientDTO = new ClientDTO
{
Name = "name",
Description = "description",
Address = "address",
Billing = "billing",
CellphoneNumber = "cellphone",
Email = "email"
};
mockRepository.Setup(r => r.Create(_mapper.Map<client>(clientDTO)))
.Returns(1);
var _baseCRUDRepository = mockRepository.Object;
var _sut = new ClientCRUDDomainService(_logger, _mapper, _baseCRUDRepository);
var response = _sut.Create(clientDTO);
这是抛出的错误
Moq.MockException: 'IBaseCRUDRepository<client>.Create(client) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.'
这是我要测试的方法:
public int Create(clientDTO entity)
{
var entityDB = _mapper.Map<clientDB>(entity);
return _baseCRUDRepository.Create(entityDB);
}
这是DTO类
public class ClientDTO
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Billing { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string CellphoneNumber { get; set; }
public int[]? Users { get; set; }
}
这是数据库类
public partial class client
{
public int Id { get; set; }
public string name { get; set; } = null!;
public string? description { get; set; }
public string? billing { get; set; }
public string? address { get; set; }
public string? email { get; set; }
public string? cellphone_number { get; set; }
}
这是映射器:
public class DomainMapper : Profile
{
public DomainMapper() : base()
{
var configuration = new MapperConfiguration(cfg =>
{
cfg.AllowNullCollections = true;
});
configuration.CompileMappings();
configuration.AssertConfigurationIsValid();
CreateMap<ClientDTO, client>()
.ForMember(db => db.Id, opt => opt.MapFrom(dto => dto.Id))
.ForMember(db => db.cellphone_number, opt => opt.MapFrom(dto => dto.CellphoneNumber))
.ReverseMap()
.ForMember(dto => dto.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dto => dto.CellphoneNumber, opt => opt.MapFrom(src => src.cellphone_number));
}
}
问题就在这里:
mockRepository.Setup(r => r.Create(_mapper.Map<client>(clientDTO)))
.Returns(1);
此设置意味着,每次使用此
exact参数调用
Create
方法时,都会返回 1。由于 client 是一个没有相等覆盖的类,因此它意味着具有相同引用的类。这显然不会发生,因为映射器每次都会返回新的类。
解决方案是使用内置参数指定约束
It.Is
:
mockRepository.Setup(
r => r.Create(
It.Is<client>(
c => \** your condition here **\
)
)
)
.Returns(1);
或者使用 this nuget 它将 FluentAssertions 的等价性检查添加到 Moq:
mockRepository.Setup(
r => r.Create(
Its.EquivalentTo(
/** your reference class here **/
)
)
)
.Returns(1);
我还强烈建议不要在测试中使用真正的映射器并模拟它,因为在此测试中您正在 ClientCRUDDomainService 中测试逻辑,而不是映射。对于映射器本身,您可以编写另一个测试,仅测试映射。在这种情况下,测试将变得微不足道:
var mockMapper = new Mock<IMapper>();
var clientDTO = new ClientDTO();
var client = new client();
mockMapper.Setup(x => x.Map<client>(clientDTO)).Returns(client);
mockRepository.Setup(r => r.Create(client)).Returns(1);