NSubstitute
NSubstitute copied to clipboard
NSubstitute : Can not return value of type Task`1 for IMapperBase.Map (expected type List`1)
I write a unit test, in the test I want to test my CashCapitalService.
in my service, I used AutoMapper for mapping my model to dto and reverse.
My Service is:
public class CashCapitalService : ICashCapitalService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public CashCapitalService(IUnitOfWork unitOfWork, IMapper mapper)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
}
public async Task<List<CashCapitalInsertAndUpdateDto>> GetAllAsync()
{
var allAsync = await _unitOfWork.CashCapitalRepository.GetAllAsync();
List<CashCapitalInsertAndUpdateDto> cashCapitalInsertAndUpdateDtos = _mapper.Map<List<CashCapitalInsertAndUpdateDto>>(source:allAsync);
return cashCapitalInsertAndUpdateDtos;
}
public class CashCapitalService : ICashCapitalService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public CashCapitalService(IUnitOfWork unitOfWork, IMapper mapper)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
}
public async Task<List<CashCapitalInsertAndUpdateDto>> GetAllAsync()
{
var allAsync = await _unitOfWork.CashCapitalRepository.GetAllAsync();
List<CashCapitalInsertAndUpdateDto> cashCapitalInsertAndUpdateDtos = _mapper.Map<List<CashCapitalInsertAndUpdateDto>>(source:allAsync);
return cashCapitalInsertAndUpdateDtos;
}
as you can see Automapper profile is:
public class CashCapitalInsertDtoProfile : Profile
{
public CashCapitalInsertDtoProfile()
{
CreateMap<CashCapitalInsertAndUpdateDto, CashCapital>().ReverseMap();
}
}
and in my unit test:
public class CashCapitalServiceTest
{
private readonly CashCapitalService _cashCapitalService;
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public CashCapitalServiceTest()
{
_unitOfWork = Substitute.For<IUnitOfWork>();
_mapper = Substitute.For<IMapper>();
_cashCapitalService = new CashCapitalService(_unitOfWork, _mapper);
}
[Fact]
public async Task GetAllAsync_Should_GetAllCashCapital()
{
//Arrange
_unitOfWork.CashCapitalRepository.GetAllAsync().Returns(new List<CashCapital>());
var cashCapitals = new List<CashCapital>()
{
new CashCapital()
{
InsertDateTime = DateTime.Now,
AmountRial = 250000000,
Description = "tv,a lj,v"
}
};
var cashCapitalInsertAndUpdateDtos = new List<CashCapitalInsertAndUpdateDto>()
{
new CashCapitalInsertAndUpdateDto()
{
AmountRial = 250000000, Description = "tv,a lj,v"
}
};
//var returnValue = _mapper.Map(Arg.Any<List<CashCapital>>(), Arg.Any<List<CashCapitalInsertAndUpdateDto>>());
//_cashCapitalService.GetAllAsync().Returns(returnValue);
_mapper.Map(cashCapitals, cashCapitalInsertAndUpdateDtos).Returns(new List<CashCapitalInsertAndUpdateDto>()
{
new CashCapitalInsertAndUpdateDto()
{
AmountRial = 250000000, Description = "tv,a lj,v"
}
});
var resultValue = _mapper.Map(cashCapitals, cashCapitalInsertAndUpdateDtos);
_cashCapitalService.GetAllAsync().ReturnsForAnyArgs(resultValue);
//Act
var all = await _cashCapitalService.GetAllAsync();
//Assert
all.Should().BeOfType<List<CashCapitalInsertAndUpdateDto>>();
await _unitOfWork.CashCapitalRepository.Received(1).GetAllAsync();
}
}
When I run this test, failed and give me an error:
Message: NSubstitute.Exceptions.CouldNotSetReturnDueToTypeMismatchException : Can not return value of type Task
1 for IMapperBase.Map (expected type List1).
I'm new in unit testing and the NSubstitute library, I don't know how to mock the AutoMapper.
Hi @djary ,
I'm not familiar with AutoMapper sorry so I can't give you a direct answer.
Would you be able to try adding the NSubstitute Analyzers to your test project? I have a hunch this may be due to mocking a non-virtual member of a class, and the Analyzers will pick up any issues with this.
There is lots of code missing to get this into an working example. I can only guess from what I see.
Never, ever use Returns on Non-Substitutes. So all these _cashService.XXX().Returns are wrong.
If the part about the service is correct, I can see that you call _mapper.Map<List<CashCapitalInsertAndUpdateDto>>(object)
So while the interface definition of IMapper is generic, NSubstitute can only set up concrete methods.
So you have to use
_mapper.Map<List<CashCapitalInsertAndUpdateDto>>(cashCapitals).Returns(cashCapitalInsertAndUpdateDtos);
But be aware of what you are creating for a test.
I see this all the time among our junior developers. They set up their substitutes to return specific values and then test that these values come back.
That is a waste of time in my opinion.
Normally you put the Received statement in your assert part of the test.
All you want to know is, if the correct method was called. It is not the task of a test to test NSubstitute.