2

I am working on a .net core web api project and writing some unit tests for my methods. One of my test cases is unable to calculate expected output.

In test project, I have the following code:

_mockBaseDbContext.Setup(c => c.Transactions).Returns(mockTransactions.Object);
var actualResult = await _service.Get(transactionId);

In the web api, I have the corresponding method as follows:

public async Task<TransactionViewModel> Get(Guid id)
{
     var transaction = await GetById(id);
     var result = _mapper.Map<TransactionViewModel>(transaction);
     return result;
}

So, when i run the test case, it finds the transaction var transaction = await GetById(id); //works fine but it just can not map the Transaction to TransactionViewModel

_mapper.Map<TransactionViewModel>(transaction); //returns null

I have the mapping profile in startup.cs and it works when I run the web api, I mean I have written an endpoint that takes guid as a parameter and call my meyhod, then it returns the transaction view model without any trouble.

CreateMap<Transaction, TransactionViewModel>()
                .ForMember(dest => dest.Client, opt => opt.MapFrom(src => src.Client))
                .ForMember(dest => dest.ShopId, opt => opt.MapFrom(src => src.ShopId));

So my question is that is there a way to get the view model that is returned from my Get method? Thanks in advance.

5
  • If _mapper is of type IMapper and you're injecting it into the Controller via the constructor, you can just create a Mock<IMapper> in your test, Setup the Map<TransactionViewModel> function, and pass the mocked IMapper to your controller in the test. Commented Sep 8, 2022 at 14:31
  • Yes, _mapper is of type IMapper and I've tried your approach. However, I couldn't make it work. It was like: private Mock<IMapper> _mockMapper; and in the constructor there was _mockMapper = new Mock<IMapper>(); I guess I could not come up with the correct form of syntax in terms of Setup function. By the way, where am i supposed to set up my mapper? In the constructor or in the test method just like db setup? Commented Sep 8, 2022 at 18:21
  • @JoshuaRobinson I tried these in my test method: _mapper.Setup(m => m.Map<TransactionViewModel>(It.IsAny<Transaction>())) .Returns(new TransactionViewModel()); ---AND--- _mockMapper.Setup(m => m.Map<TransactionViewModel>(It.IsAny<object>())) .Returns(new TransactionViewModel()); --- There is no compile time error but it just returns empty view model as written in .Returns section of the setup. Maybe, we need something else rather than new TransactionViewModel() Commented Sep 8, 2022 at 18:39
  • 1
    And as far as I understand we should NOT mock auto mappers. Commented Sep 8, 2022 at 19:07
  • You don't mock AutoMapper, you use it. Put your mappings into classes derived from Profile class. In your test create a mapper configuration from your profile and a mapper from your config. Then use this real instance in your test. By that way you test, if you configured AutoMapper correctly. You don't have to test if AutoMapper does what it should. That makes the project by herself. Commented Nov 2, 2022 at 11:55

1 Answer 1

5

source: https://www.thecodebuzz.com/unit-test-mock-automapper-asp-net-core-imapper/

You can use your profile mapper as follow :

private static IMapper _mapper;
public testContsructor()
{
    if (_mapper == null)
    {
        var mappingConfig = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile(new UserProfile());
        });
        IMapper mapper = mappingConfig.CreateMapper();
        _mapper = mapper;
    }
}
Sign up to request clarification or add additional context in comments.

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.