views:

293

answers:

2

So, I'm using moq for testing, but I ran into a problem that prevents me from mocking correctly, at least I think so. This is my repository class:

public interface IAccountsRepository
    {
     IQueryable<Account> Accounts { get; }
     IQueryable<Account> AccountsPaged(int pageSize, int selectedPage);
    }

This is one of the implementations (fake):

public class FakeAccountsRepository : IAccountsRepository
    {
     private static readonly IQueryable<Account> FakeAccounts = new List<Account> {
     new Account {RegistrationEmail = "[email protected]"},
     new Account {RegistrationEmail = "[email protected]"},
     new Account {RegistrationEmail = "[email protected]"},
     new Account {RegistrationEmail = "[email protected]"},
     new Account {RegistrationEmail = "[email protected]"}
     }.AsQueryable();

     public IQueryable<Account> Accounts
     {
      get { return FakeAccounts; }
     }

     public IQueryable<Account> AccountsPaged(int pageSize, int selectedPage)
     {
      return FakeAccounts.Skip((selectedPage - 1)*pageSize).Take(pageSize).AsQueryable();
     }
    }

This is a Controller definition that works perfectly with real page and fake or sql data (IoC) inside a real web page:

public class AccountsController : Controller
    {
     private IAccountsRepository _accountsRepository;
        public int PageSize = 3;

     public AccountsController(IAccountsRepository accountsRepository)
     {
      this._accountsRepository = accountsRepository;
     }

     public ViewResult List(int selectedPage)
     {
               return View(_accountsRepository.AccountsPaged(PageSize, selectedPage).ToList());
     }
    }

This is a moq method:

static IAccountsRepository MockAccountsRepository(params Account[] accs)
     {
      // Generate an implementor of IAccountsRepository at runtime using Moq
      var mockProductsRepos = new Moq.Mock<IAccountsRepository>();
      mockProductsRepos.Setup(x => x.Accounts).Returns(accs.AsQueryable());
      return mockProductsRepos.Object;
     }

it works fine with this implementation of List pagination:

public ViewResult List(int selectedPage)
     {
      return View(_accountsRepository.Accounts.Skip((selectedPage - 1) * PageSize).Take(PageSize).ToList());

     }

but it fails when using this:

public ViewResult List(int selectedPage)
     {
      return View(_accountsRepository.AccountsPaged(PageSize, selectedPage).ToList());
     }

Without changing test and changing only List implementation (doing pagination only on .Accounts) it all works, but when I try to use AccountsPaged method, it Fails returning no elements. In real usage, on a web page, it works both ways.

Please advise, thank you.

EDIT: If I do this:

mockProductsRepos.Setup(x => x.AccountsPaged(Moq.It.IsAny<int>(), Moq.It.IsAny<int>())).Returns(accs.AsQueryable());

I get 5 items returned instead of 2.

+2  A: 

You didn't setup AccountsPaged method in your mock

EDIT: Now that you setup AccountsPaged, you didn't setup it properly. Here how to setup it properly:

mockProductsRepos
   .Setup(x => x.AccountsPaged(Moq.It.IsAny<int>(), Moq.It.IsAny<int>()))
   .Returns( (int pageSize, int selectedPage) => accs.Skip((selectedPage-1)*pageSize).Take(pageSize).AsQueryable() );
Michaël Larouche
I did setup it now, like I've added to the post above, but it gives me 5 items instead of 2 - which would be expected if .List() call worked correctly. I don't know how could it be and why does it return full members? Is there a way to step by step debug of the moq setup?
BuzzBubba
+1  A: 

I didn't parse through your code in any depth, but a general rule of thumb is - When in doubt regarding mock correctness, use strict mocking to flush out any missing expectations:

var mock = new Mock(MockBehavior.Strict);

that way you will get explicit indications of any unexpected calls issued by the SUT which you forgot to mock.

Addys