1

I have the following piece of code that I'm trying to mock out using Moq, specifically _userRepository.Find():

List<string> importEmails = ocrImportCentres.Select(c => c.CentreAdministratorEmail).Where(e => !string.IsNullOrWhiteSpace(e)).ToList();

 var existingUsersWithEmail =
            _userRepository.Find(
                x =>
                    importEmails.Contains(
                        x.PersonalDetailsHistory.OrderByDescending(h => h.DateCreated).FirstOrDefault().Email))
                .Select(o => new
                {
                    o.PersonalDetailsHistory.FirstOrDefault().Email,
                    (o as OCRInstitutionAdmin).UniqueId 
                });

The Find() methods are defined within IRepository:

IQueryable<T> Find(Expression<Func<T, bool>> predicate);
IQueryable<T> Find(Expression<Func<T, bool>> predicate = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "");

Moq setup within my unit test:

_userRepository.Setup(
            x =>
                x.Find(It.IsAny<Expression<Func<User, bool>>>(),
                    It.IsAny<Func<IQueryable<User>, IOrderedQueryable<User>>>(), It.IsAny<string>()))
            .Returns(existingAdmins.AsQueryable);

However when the unit test is ran _userRepository.Find() doesn't return the expected test object, after looking at the _userRepository.Verify(); I can see that my setup doesn't match the perform invocation and hence why I don't get my expected object returned.

Performed invocations:

IRepository`1. Find(x => value(OCRExamCreator.BusinessLogic.Services.OCRImportCentreManagementService+<>c__DisplayClasse).importEmails.Contains(x.PersonalDetailsHistory.OrderByDescending(h => h.DateCreated).FirstOrDefault().Email))

I did have the unit test passing and the Moq _userRepository.Setup working until I had to change the _userRepository.Find() LINQ to prevent the following exception:

{"Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries."}

I have tried changing _userRepository.Setup() however I can't get it to return the test data I need, any help/pointers would be much appreciated

forsvarir
  • 10,749
  • 6
  • 46
  • 77
Rocy
  • 35
  • 8
  • 1
    It looks to me like you are defining in Setup() to expect Find() with 4 parameters to be called, but Verify() is telling you that it was called with a single parameter, but that call to Find() is pretty hairy so I may be reading that wrong. – Sven Grosen Dec 19 '13 at 20:12
  • I did try setting up the Setup() using .Find() with a single parameter, e.g. mocking out IQueryable Find(Expression> predicate); however this resulted in a parameter count mismatch Exception which led me to use the other implementation of Find(). Thanks for looking. – Rocy Dec 19 '13 at 20:55
  • As ledbutter pointed out the find method was being called with a single parameter. I don't really understand why this fixed the issue but I changed my setup to use a single parameter on the Find method but also overload the Returns method like so..._userRepository.Setup( x => x.Find(It.IsAny>>())) .Returns((Expression> predicate) => existingAdmins.AsQueryable()); This link helped me out http://stackoverflow.com/questions/5196669/moqing-methods-where-expressionfunct-bool-are-passed-in-as-parameters – Rocy Dec 23 '13 at 16:41

1 Answers1

1

Fixed the issue by changing the setup() to use a single parameter on the Find method but also overloaded the Returns method like so...

_userRepository.Setup( x => x.Find(It.IsAny<Expression<Func<User, bool>>>())) 
               .Returns((Expression<Func<User, bool>> predicate) => 
                                                             existingAdmins.AsQueryable());

This link helped:

Moq'ing methods where Expression<Func<T, bool>> are passed in as parameters

Community
  • 1
  • 1
forsvarir
  • 10,749
  • 6
  • 46
  • 77