23

I have .NET Core 2.0 Project which contains Repository pattern and xUnit testing.

Now, here is some of it's code.

Controller:

public class SchedulesController : Controller
{
    private readonly IScheduleRepository repository;
    private readonly IMapper mapper;

    public SchedulesController(IScheduleRepository repository, IMapper mapper)
    {
        this.repository = repository;
        this.mapper = mapper;
    }

    [HttpGet]
    public IActionResult Get()
    {
        var result = mapper.Map<IEnumerable<Schedule>, IEnumerable<ScheduleDto>>(source: repository.items);
        return new OkObjectResult(result);
    }
}

My Test Class:

public class SchedulesControllerTests
{
    [Fact]
    public void CanGet()
    {
        try
        {
            //Arrange
            Mock<IScheduleRepository> mockRepo = new Mock<IScheduleRepository>();
            mockRepo.Setup(m => m.items).Returns(new Schedule[]
            {
                new Schedule() { Id=1, Title = "Schedule1" },
                new Schedule() { Id=2, Title = "Schedule2" },
                new Schedule() { Id=3, Title = "Schedule3" }
            });

            var mockMapper = new Mock<IMapper>();
            mockMapper.Setup(x => x.Map<Schedule>(It.IsAny<ScheduleDto>()))
                .Returns((ScheduleDto source) => new Schedule() { Title = source.Title });

            SchedulesController controller = new SchedulesController(repository: mockRepo.Object, mapper: mockMapper.Object);

            //Act
            var result = controller.Get();

            //Assert
            var okResult = result as OkObjectResult;
            Assert.NotNull(okResult);

            var model = okResult.Value as IEnumerable<ScheduleDto>;
            Assert.NotNull(model);

        }
        catch (Exception ex)
        {
            //Assert
            Assert.False(false, ex.Message);
        }
    }
}

Issue I Am facing.

My Issue is that when I run this code with database context and execute Get() method, it works fine, it gives me all results.

But when I tries to run test case, it's not returning any data of Dto object. When I debugged I found that

  1. I am getting my test object in controller using mockRepo.

  2. But it looks like Auto mapper is not initialized correctly, because while mapping it's not returning anything in

    var result = mapper.Map<IEnumerable<Schedule>, IEnumerable<ScheduleDto>>(source: repository.items);

What I tried So Far?

I followed all this answers but still it's not working.

Mocking Mapper.Map() in Unit Testing

How to Mock a list transformation using AutoMapper

So, I need help from someone who is good in xUnit and automapper, and need guidance on how to initialize mock Mapper correctly.

4
  • 2
    You seem to be using a different signature of Map in your code and your moq setup. Instead of mocking Map<dest> try mocking the Map<source, dest> method instead. Commented Apr 20, 2018 at 10:32
  • 1
    @jcemoller finally it worked without mocking, I just created mapper object and injected it with my profile. Commented Apr 20, 2018 at 11:11
  • 1
    @Bharat was writing that up as an answer when you left your comment. No need for me to do it now. You can add it as a self answer to your question. Here is a similar answer I provided here stackoverflow.com/questions/39864288/…. Note it is using a different mocking framework but the automapper part is applicable. Commented Apr 20, 2018 at 11:12
  • Thanks @Nkosi, I fixed this issue and it's working fine,I Posted my answer but there is one another tricky issue, which I am trying to resolve from the morning, I think I will need your help over there. Commented Apr 20, 2018 at 11:26

2 Answers 2

65

Finally it worked for me, I followed this way How to Write xUnit Test for .net core 2.0 Service that uses AutoMapper and Dependency Injection?

Here I am posting my answer and Test Class so if needed other SO's can use.

public class SchedulesControllerTests
{
    [Fact]
    public void CanGet()
    {
        try
        {
            //Arrange
            //Repository
            Mock<IScheduleRepository> mockRepo = new Mock<IScheduleRepository>();
            var schedules = new List<Schedule>(){
                new Schedule() { Id=1, Title = "Schedule1" },
                new Schedule() { Id=2, Title = "Schedule2" },
                new Schedule() { Id=3, Title = "Schedule3" }
            };

            mockRepo.Setup(m => m.items).Returns(value: schedules);

            //auto mapper configuration
            var mockMapper = new MapperConfiguration(cfg =>
            {
                cfg.AddProfile(new AutoMapperProfile());
            });
            var mapper = mockMapper.CreateMapper();

            SchedulesController controller = new SchedulesController(repository: mockRepo.Object, mapper: mapper);

            //Act
            var result = controller.Get();

            //Assert
            var okResult = result as OkObjectResult;
            if (okResult != null)
                Assert.NotNull(okResult);

            var model = okResult.Value as IEnumerable<ScheduleDto>;
            if (model.Count() > 0)
            {
                Assert.NotNull(model);

                var expected = model?.FirstOrDefault().Title;
                var actual = schedules?.FirstOrDefault().Title;

                Assert.Equal(expected: expected, actual: actual);
            }
        }
        catch (Exception ex)
        {
            //Assert
            Assert.False(false, ex.Message);
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

-1

I needed to inject IMapper, use ProjectTo to get a mapped IQueryable, then implement some more logic on the queryable after the map. So here's what I did to mock it:

var models = new object[]
{
    ⋮
}.AsQueryable();
var mapper = new Mock<IMapper>();
mapper.Setup(x => x.ProjectTo(
        It.IsAny<IQueryable>(),
        It.IsAny<object>(),
        It.IsAny<Expression<Func<object, object>>[]>()))
    .Returns(models);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.