Reputation: 31
I'm creating a random object that I'm expecting back from the test, and using the ReturnsAsync method when setting up the mock repo. The controller inside the Unit Test is returning null, however.
The main difference between my code and a lot of the others is that I'm using AutoMapper to return the DTO object in my controller as an OK object. I'm not sure if that's causing my issue.
Controller Instantiation
private readonly ISuperHeroRepo _repo;
public IMapper _mapper { get; }
public SuperHeroController(ISuperHeroRepo repo, IMapper mapper)
{
_repo = repo;
_mapper = mapper;
}
Repo Method
public async Task<SuperHero> GetSuperHero(int id)
{
return await _db.SuperHeros.FindAsync(id);
}
Mapper Profile
public class SuperHeroProfiles : Profile
{
public SuperHeroProfiles()
{
//Source -> Target
CreateMap<SuperHero, SuperHeroReadDTO>()
.ForMember(target => target.LegalName, option => option.MapFrom(source => $"{source.LegalFirstName} {source.LegalLastName}"))
.ForMember(target => target.Jurisdiction, option => option.MapFrom(source => $"{source.JurisdictionCity}, {source.JurisdictionState}"));
CreateMap<SuperHero, SuperHeroDTO>();
}
}
Controller Method
[HttpGet("{id}")]
public async Task<ActionResult<SuperHeroReadDTO>> Get(int id)
{
var hero = await _repo.GetSuperHero(id);
if (hero == null)
{
return NotFound("Hero Not Found");
}
else
{
// This is where it might be breaking
return Ok(_mapper.Map<SuperHeroReadDTO>(hero));
}
}
Unit Test
// Instantiated
readonly Mock<ISuperHeroRepo> repoMock = new();
readonly Mock<IMapper> mapperMock = new();
private readonly Random random = new();
........
[Fact]
public async Task Get_WithExistingHero_ReturnsExpectedSuperHero()
{
// Arrange
SuperHero expected = CreateRandomSuperHero();
repoMock.Setup(repo => repo.GetSuperHero(It.IsAny<int>()))
.ReturnsAsync(expected);
var controller = new SuperHeroController(repoMock.Object, mapperMock.Object);
// Act - This returns null. Debugging in the controller, I get the object back from repo
var result = await controller.Get(random.Next());
// Assert
Assert.IsType<SuperHeroReadDTO>(result.Value);
var dto = result.Value;
Assert.Equal(expected.SuperHeroName, dto.SuperHeroName);
Assert.Equal($"{expected.LegalFirstName} {expected.LegalLastName}", dto.LegalName);
Assert.Equal($"{expected.JurisdictionCity}, {expected.JurisdictionState}", dto.Jurisdiction);
}
Edited: Added the controller instantiation, and the Mapper Profile. Not sure if it'll add more info.
Upvotes: 2
Views: 767
Reputation: 31
@shree.pat18 was indeed correct. I did end up needing to set up the Mapper object in the Unit Test and passing it back into the controller. I'll need to refactor, but here below is what resolved it:
[Fact]
public async Task Get_WithExistingHero_ReturnsExpectedSuperHero()
{
// Arrange
SuperHero expected = CreateRandomSuperHero();
repoMock.Setup(repo => repo.GetSuperHero(It.IsAny<int>()))
.ReturnsAsync(expected);
// Setup of the mock Mapper
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new SuperHeroProfiles());
});
var mapper = mockMapper.CreateMapper();
var controller = new SuperHeroController(repoMock.Object, mapper);
// Act
var result = await controller.Get(random.Next());
// Assert
Assert.IsType<SuperHeroReadDTO>(result.Value);
var dto = result.Value;
Assert.Equal(expected.SuperHeroName, dto.SuperHeroName);
Assert.Equal($"{expected.LegalFirstName} {expected.LegalLastName}", dto.LegalName);
Assert.Equal($"{expected.JurisdictionCity}, {expected.JurisdictionState}", dto.Jurisdiction);
}
Upvotes: 1