Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expectation on Mock Object doesn't seem to be met (Moq)

I'm experiencing some odd behavior in Moq - despite the fact that I setup a mock object to act a certain way, and then call the method in the exact same way in the object I'm testing, it reacts as if the method was never called.

I have the following controller action that I'm trying to test:

public ActionResult Search(string query, bool includeAll)
{
    if (query != null)
    {
        var keywords = query.Split(' ');
        return View(repo.SearchForContacts(keywords, includeAll));
    }
    else
    {
        return View();
    }
}

My unit test code:

public void SearchTestMethod() // Arrange
    var teststring = "Anders Beata";
    var keywords = teststring.Split(' ');
    var includeAll = false;
    var expectedModel = dummyContacts.Where(c => c.Id == 1 || c.Id == 2);
    repository
        .Expect(r => r.SearchForContacts(keywords, includeAll))
        .Returns(expectedModel)
        .Verifiable();

    // Act
    var result = controller.Search(teststring, includeAll) as ViewResult;

    // Assert
    repository.Verify();
    Assert.IsNotNull(result);
    AssertThat.CollectionsAreEqual<Contact>(
        expectedModel, 
        result.ViewData.Model as IEnumerable<Contact>
    );
}

where AssertThat is just a class of my own with a bunch of assertion helpers (since the Assert class can't be extended with extension methods... sigh...).

When I run the test, it fails on the repository.Verify() line, with a MoqVerificationException:

Test method MemberDatabase.Tests.Controllers.ContactsControllerTest.SearchTestMethod()
threw exception:  Moq.MockVerificationException: The following expectations were not met:
IRepository r => r.SearchForContacts(value(System.String[]), False)

If I remove repository.Verify(), the collection assert fails telling me that the model returned is null. I have debugged and checked that query != null, and that I am taken into the part of the if block where the code is run. No problems there.

Why doesn't this work?

like image 451
Tomas Aschan Avatar asked Aug 02 '09 22:08

Tomas Aschan


1 Answers

I suspect it's because the array you're passing into your mocked repository (the result of teststring.Split(' ')) is not the same object as the one that actually gets passed in from the Search method (the result of query.Split(' ')).

Try replacing the first line of your setup code with:

repository.Expect(r => r.SearchForContacts(
    It.Is<String[]>(s => s.SequenceEqual(keywords)), includeAll))

... which will compare each element of the array passed to your mock with the corresponding element in the keywords array.

like image 100
Matt Hamilton Avatar answered Nov 15 '22 03:11

Matt Hamilton