Search code examples
c#unit-testingmoq

How to use moq to verify that a similar object was passed in as argument?


I have had a few occasions where something like this would be helpful. I have, for instance, an AccountCreator with a Create method that takes a NewAccount. My AccountCreator has an IRepository that will eventually be used to create the account. My AccountCreator will first map the properties from NewAccount to Account, second pass the Account to the repo to finally create it. My tests look something like this:

public class when_creating_an_account
{
    static Mock<IRepository> _mockedRepository;
    static AccountCreator _accountCreator;
    static NewAccount _newAccount;
    static Account _result;
    static Account _account;

    Establish context = () =>
        {
            _mockedRepository = new Mock<IRepository>();
            _accountCreator = new AccountCreator(_mockedRepository.Object);

            _newAccount = new NewAccount();
            _account = new Account();

            _mockedRepository
                .Setup(x => x.Create(Moq.It.IsAny<Account>()))
                .Returns(_account);
        };

    Because of = () => _result = _accountCreator.Create(_newAccount);

    It should_create_the_account_in_the_repository = () => _result.ShouldEqual(_account);
}

So, what I need is something to replace It.IsAny<Account>, because that doesn't help me verify that the correct Account was created. What would be amazing is something like...

public class when_creating_an_account
{
    static Mock<IRepository> _mockedRepository;
    static AccountCreator _accountCreator;
    static NewAccount _newAccount;
    static Account _result;
    static Account _account;

    Establish context = () =>
        {
            _mockedRepository = new Mock<IRepository>();
            _accountCreator = new AccountCreator(_mockedRepository.Object);

            _newAccount = new NewAccount
                {
                    //full of populated properties
                };
            _account = new Account
                {
                    //matching properties to verify correct mapping
                };

            _mockedRepository
                .Setup(x => x.Create(Moq.It.IsLike<Account>(_account)))
                .Returns(_account);
        };

    Because of = () => _result = _accountCreator.Create(_newAccount);

    It should_create_the_account_in_the_repository = () => _result.ShouldEqual(_account);
}

Notice I changed It.IsAny<> to It.IsLike<> and passed in a populated Account object. Ideally, in the background, something would compare the property values and let it pass if they all match.

So, does it exist already? Or might this be something you have done before and wouldn't mind sharing the code?


Solution

  • To stub out a repository to return a particular value based on like criteria, the following should work:

    _repositoryStub
        .Setup(x => x.Create(
            Moq.It.Is<Account>(a => _maskAccount.ToExpectedObject().Equals(a))))
        .Returns(_account);