Big Daddy
Big Daddy

Reputation: 5224

Unit Test Using Moq

I am unit-testing an async method that returns a List<T>. This method has a dependency on a mapping class/interface. In my unit-test, I am mocking the mapping class using moq. The test runs okay, and the returned list has items, but the values of the items is null. I think the problem is because I haven't stubbed-out the mapping classes methods properly. I don't have a lot of experience with testing, so any guidance is appreciated.

Test Method:

[TestMethod]
[TestCategory("CSR.Data.Tests.Services.ServiceSearchTest")]
public void SearchAccount()
    {
        // Arrange                 
        var mapper = new Mock<CSR.Data.Mapping.Interfaces.IMapper<Account, AccountDTO>>();

        mapper.Setup(i => i.Initialize());
        mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(It.IsAny<Account>);
        mapper.Setup(i => i.DomainToDto(It.IsAny<Account>())).Returns(It.IsAny<AccountDTO>);

        var service = new ServiceSearch(null,mapper.Object);         
        string accountNumber = "123";
        string accountName = "";

        // Act 
        var results = service.SearchAccount(accountNumber, accountName);            

       // Assert
        Assert.IsTrue(results.Result.Count >= 1);
        }

Method/Class That I'm Testing:

    public class ServiceSearch : IServiceSearch
    {
    public ServiceSearch(IMapper<Claim, ClaimDTO> claimMapper, IMapper<Account, AccountDTO> accountMapper)
            {
                _claimMapper = claimMapper;
                _accountMapper = accountMapper;
            }

    public async Task<List<AccountDTO>> SearchAccount(string accountNumber, string accountName)
            {
                var accounts = new List<Account>();
                var accountDTOs = new List<AccountDTO>();
                var results = await Task.Run(() => base.AccountSearch(accountNumber, accountName).Result);

                if (results != null && results.Count > 0)
                {
                    //Map DH to Domain
                    _accountMapper.Initialize();

                    foreach (AccountSearchResult result in results)
                    {
                        accounts.Add(_accountMapper.ToDomain(result));
                    }

                    //Map Domain to DTO
                    foreach (Account account in accounts)
                    {
                        accountDTOs.Add(_accountMapper.DomainToDto(account));
                    }
                }
                return accountDTOs;
            }
}

Upvotes: 2

Views: 1341

Answers (2)

Steve Mitcham
Steve Mitcham

Reputation: 5313

This isn't the best place to use a Mock object because you are going to spend a lot of time writing your test objects and mock results. The issue with the setup call is that you haven't configured anything to send back in the result. A correct example would be:

// you would fully configure this object
AccountDTO expectedResult = new AccountDTO();  

mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(expectedResult);

Now you can use the setup to configure different accountDTOs for different inputs.

You call also configure a callback to generate the account at test time:

mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns<AccountSearchResult>(sr => {
   // build and return your dto here 
});

However, unless your mapper is expensive to run or create, I think you'd better off just ensure that it is fully tested and acceptable and then use it to go ahead and generate the DTOs directly instead of trying to mock it out.

Upvotes: 1

Matt Clark
Matt Clark

Reputation: 1171

You don't actually setup an object in the ".Returns" call. You need to make sure to setup the ".Returns" to actually have an object with values.

Upvotes: 0

Related Questions