0

C# method where I am using IMapper interface

foreach (var req in listRequestMasters)
{
    var customReq = _mapper.Map<GridModel>(req);
}

by below line of code getting success assertion but not as expected result, the one record getting twice

_mockMapper.Setup(x => x.Map<GridModel>(It.IsAny<RequestMaster>())).Returns(requestGridModelMockData.FirstOrDefault());

and by below line of code getting Message:

Moq.MockException : IMapperBase.Map(RequestMaster) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.

_mockMapper.Setup(x => x.Map<List<GridModel>>(It.IsAny<RequestMaster>())).Returns(requestGridModelMockData);

remaining code

var result = await Service.GetHistoryRequestDetails(historyVMMockData);
Assert.Equal(JsonConvert.SerializeObject(requestGridModelMockData), JsonConvert.SerializeObject(result));
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
abbas ahmed
  • 283
  • 2
  • 13
  • 2
    Why do you want to mock AutoMapper? The library itself is already well tested. In your tests create a real mapper instance using the corresponding derived `Profile` class and use that in your tests. – Oliver Jun 23 '22 at 07:01
  • I didn't get you, could you give any example plz. – abbas ahmed Jun 23 '22 at 07:34
  • @abbasahmed you should be mocking what you cannot control. An external dependency that you do not have a control over is candidate for mocking. Anything that you can create by yourself (in this case the mapper), you can always create a stub instead of a mock. Check out mock vs stub vs fake. – Amogh Sarpotdar Jun 23 '22 at 08:41
  • https://stackoverflow.com/questions/346372/whats-the-difference-between-faking-mocking-and-stubbing#:~:text=Mock%20%2D%20an%20object%20on%20which,people%20simply%20call%20them%20mocks. - this elaborates difference between a mock, a stub and a fake. – Amogh Sarpotdar Jun 23 '22 at 08:42

1 Answers1

1

AutoMapper is a library that is already well tested on its own. So you should use the AutoMapper library also in your tests and not mock it, because you want to test your code and not others library code (or do you have also self written tests for ASP core, EF or something similar?).

In most environments you manage your mapping within individual Profiles. If not, you should do so and create within your test a fresh mapper (preferable in constructor) and use it as usual.

For example you have some DTOs:

public class Source
{
    public string Name { get; set; }
}

public class Destination
{
    public string Name { get; set; }
}

And somewhere else you defined the AutoMapper mappings:

public class MyProfile : Profile
{
    public MyProfile()
    {
        CreateMap<Source, Destination>();
    }
}

Then within your test class you do something like this:

public class MyTests
{
    private readonly IMapper mapper;

    public MyTests()
    {
        var config = new MapperConfiguration(cfg => cfg.AddProfile<MyProfile>());
        var mapper = config.CreateMapper();
    }

    [Fact]
    public void TestSomething()
    {
        var source = new Source { Name = "foo" };
        var sut = new SystemUnderTest(mapper);
        var result = sut.DoSomething(source);

        var expected = mapper.Map<Dest>(source);
        Assert.Equal(expected, result, DestinationComparer.Default);
    }
}

As you can see, the system under test receives the real mapper (even if you just care for an IMapper interface). You don't create a mock, stub, puppet, you name it for 3rd party libraries. You use the real implemenations, because you write tests for your code.

Maybe it makes sense to write tests checking if a 3rd party library works as expected, which helps narrow problems down when upgrading a library and still behaves the same. But these tests don't use anything of your code and just tests some library function:

[Fact]
public void CheckMapperMapsCorrectly()
{
    var source = new Source { Name = "Foo" };
    var dest = mapper.Map<Destination>(source);

    Assert.Equal(source.Name, dest.Name);
}

But that is something different and fully optional, depending on how much you trust each 3rd party library or makes sense if you already fall into that pit on an upgrade of a 3rd party library to avoid the same problem on next update.

Oliver
  • 43,366
  • 8
  • 94
  • 151