2

I've a method like this one:

    public IEnumerable<string> GetCompaniesCities()
    {
        return CompanyRepository.All()
                      .OrderBy(c => c.City)
                      .Select(c => c.City.ToUpper())
                      .Distinct().ToList();
    }

How can I test (using moq) that OrderBy (c => c.City) is called? And Select(c => c.City.ToUpper() and Distinct()?

I'm getting

Invalid verify on a non-virtual (overridable in VB) member: x => x.All().OrderBy(c => c.City)

Note: It's a unit test, not an integration test, so I'm not going to the db

Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116
polonskyg
  • 4,269
  • 9
  • 41
  • 93
  • 3
    Don't test internals like this but test whether or not the method returns what it should and whether it is in the right order. – Jeroen Vannevel Dec 08 '14 at 21:15
  • The problem is that it's a unit test, not an integration test, so I'm not going to the db – polonskyg Dec 08 '14 at 21:31
  • 3
    That is not the way to avoid an integration test. You should mock the repository instead and inject your in-memory data in it (look into dependency injection and frameworks like unity and ninject) . – Jeroen Vannevel Dec 08 '14 at 21:33
  • Depending upon your Database settings you may want to OrderBy after you to the ToUpper conversions. If you DB is case sensitive the Cities won't be ordered correctly if you have a mixture of lower and upper case cities. – Mike Burdick Dec 08 '14 at 22:34

3 Answers3

3

You wouldn't test that OrderBy is being called, it's much easier to just test that the strings returned are ordered. I.e., with NUnit:

Assert.That(sut.GetCompaniesCities(), Is.Ordered);

Also with Moq you can't test that an extension method like OrderBy is called, it's just not possible.


To address your comment about not being able to go to the database, you're right that mocking your dependencies removes the need to go to the database. But you can mock their return values so you can simulate as if they did hit the database. So here, your repository is a dependency and you'd mock All() to return a list of unsorted values:

var companiesUnsorted = new Company[] { 
    new Company { City = "Xyz" },
    new Company { City = "Abc" }
};
var mockRepository = new Mock<ICompanyRepository>();
mockRepository.Setup(p => p.All()).Returns(companiesUnsorted);

var sut = new WhateverClassYourCodeSampleIsFrom(mockRepository.Object);

Then you'd just perform the assertion above.

Community
  • 1
  • 1
Patrick Quirk
  • 23,334
  • 2
  • 57
  • 88
  • The problem is that it's a unit test, not an integration test, so I'm not going to the db – polonskyg Dec 08 '14 at 21:31
  • That's fine, presumably you're setting up your repository to return a list, right? Just have `.All()` return a list in non-sorted order, and verify the output of `GetCompaniesCities()` is sorted. No db interaction required... – Patrick Quirk Dec 08 '14 at 21:35
0

You cannot do that simply because moq cannot mock extension methods. And this is because moq is using inheritance, which an extension method does not have

alexo
  • 936
  • 8
  • 16
0

What you want to do is Moq the CompanyRepository object All method in your Unit Test. Inject the CompanyRepository Moq into the class containing the GetCompaniesCities() method.

Then populate the Moq appropriately and have your Unit Test validate the GetCompaniesCities() method returns the expected result. You don't care how GetCompaniesCities is coded only that it returns the correct value.

Mike Burdick
  • 838
  • 6
  • 5