Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq.Mock<Expression<Func<T,bool>>>() - how to setup expressions into a Mock using Moq

I have been read a lot of others QA about this topic and I still can't find the solution to my problem, so I have decide to expose my case.

I have this interface

public interface IRepository<T> where T : class, IEntity 
{
    IQueryable<T> Find(Expression<Func<T, bool>> predicate);
    T FindIncluding(int id, params Expression<Func<T, object>>[] includeProperties);
}

And this is the basic structure of the method that contains the Mock that I would like to setup

public PeopleController CreatePeopleController()
{
    var mockUnitofWork = new Mock<IUnitOfWork>();
    var mockPeopleRepository = new Mock<IRepository<Person>>();

    mockPeopleRepository.Setup(r=>r.Find().Returns(new Person(){});
    mockUnitofWork.Setup(p => p.People).Returns(mockPeopleRepository.Object);
    return new PeopleController(mockUnitofWork.Object);
}

I have been trying to setup the Mock using this way:

public PeopleController CreatePeopleController()
{
    var mockUnitofWork = new Mock<IUnitOfWork>();
    var mockPeopleRepository = new Mock<IRepository<Person>>();

    mockPeopleRepository.Setup(r=>r.Find(It.isAny<Expression<Func<Person,bool>>>()).Single()).Returns(new Person(){});
    mockUnitofWork.Setup(p => p.People).Returns(mockPeopleRepository.Object);
    return new PeopleController(mockUnitofWork.Object);
}

But the system always throws the same exception "System.NotSupportedException: Expression references a method that does not belong to the mocked object .... "

Also I would like to add that I am using MSTest and Moq

I know that setup a Mock using Expression is not easy and not recommended, but it is very important for me because "Find" is a method that I use a lot in my app

like image 421
gustavotroconis Avatar asked Nov 02 '11 14:11

gustavotroconis


People also ask

How do you mock a method in Moq?

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it. Finally, we call the method we are testing and assert the results.

What can be mocked with Moq?

You can use Moq to create mock objects that simulate or mimic a real object. Moq can be used to mock both classes and interfaces.

What is Moq mocking framework?

Moq is a mocking framework built to facilitate the testing of components with dependencies. As shown earlier, dealing with dependencies could be cumbersome because it requires the creation of test doubles like fakes. Moq makes the creation of fakes redundant by using dynamically generated types.

Is Moq a testing framework?

The Moq framework is an open source unit testing framework that works very well with . NET code and Phil shows us how to use it.


1 Answers

The problem is that you're trying to setup the Single() extension method as part of your mocking. The setup call needs to have the result of your method -- not the result of your method with some extension method subsequently applied to it. I'd try this:

    [TestMethod]
    public void MyTestMethod()
    {
        var myMock = new Mock<IRepository<Person>>();
        myMock.Setup(r => r.Find(It.IsAny<Expression<Func<Person, bool>>>())).Returns(new List<Person>() { new Person() }.AsQueryable());

        Assert.IsTrue(true);
    }

Here, you're just stubbing your Find() method with setup, and doing all of the other stuff in the Returns() clause. I'd suggest that approach in general. Setup should mirror your mocked item exactly, and you can do a bunch of black magic for the Returns() (or Throws() or whatever) call to get it to do what you want.

(When I ran that code in VS, it passed, so it wasn't throwing an exception)

like image 178
Erik Dietrich Avatar answered Sep 20 '22 08:09

Erik Dietrich