views:

77

answers:

2

I am trying to use Rhino Mocks to mock the following lambda, but keep hitting a brick wall

var result = rep.Find<T>(x => (x as IEntity).ID == (entity as IEntity).ID).FirstOrDefault();

Any ideas?

+2  A: 

In a unit test, you have the system under test (SUT) and its collaborators. The goal of mocking is to replace the collaborators by something that you have full control over. That way you can set up different test cases and you can focus on testing just the behavior of the system under test, and nothing else.

In this case, I assume the rep object is the SUT. The lambda that you pass to the SUT's Find method could be considered a collaborator. Since you already have full control over that lambda, it doesn't really make sense to try to mock it with Rhino Mocks.

I'll try to give an example of unit test involving Rhino Mocks and lambdas anyway ;-) This is an example test which creates a predicate stub that always returns false, and which verifies that the Find method actually invoked that predicate:

[Test]
public void Find_returns_nothing_if_predicate_always_false()
{
   var predicateStub = MockRepository.GenerateStub<Func<Entity,bool>>();
   predicateStub.Stub(x => x(Arg<Entity>.Is.Anything)).Return(false);

   var repository = new Repository();
   var entities = repository.Find(predicateStub);

   Assert.AreEqual(0, entities.Count(), 
      "oops, got results while predicate always returns false");
   predicateStub.AssertWasCalled(x => x(Arg<Entity>.Is.Anything));
}

Of course, as in your own example, you don't really need Rhino Mocks here. The whole point of the lambda syntax is to make it easy to provide an implementation in-place:

[Test]
public void Find_returns_nothing_if_predicate_always_false()
{
   bool predicateCalled = false;
   Func<Entity,bool> predicate = x => { predicateCalled = true; return false; };

   var repository = new Repository();
   var entities = repository.Find(predicate);

   Assert.AreEqual(0, entities.Count(), 
      "oops, got results while predicate always returns false");
   Assert.IsTrue(predicateCalled, "oops, predicate was never used");
}
Wim Coenen
+1 I've never seen a lambda that needed mocking.
Jay
Yes you are correct, but all I am trying to do is Mock the line of code at the moment as I am not testing that line.
Coppermill
+1  A: 

Found the answer I was after

repository.Expect(action => action.Find<Entity>(x => x.ID == 0)).IgnoreArguments().Return(entities).Repeat.Any();
Coppermill
This is the same conclusion that I had come to, but unfortunately it still leaves a hole in my ability to unit test (and yours I presume). If I had a test that required multiple calls to the repository.Find method using different parameters, how do I setup a mock for that? I need to mock an Expression<Func<T,bool>>, and the reference created for the expression when setting up the mock is not going to be equivalent to the Expression that is created later in code because it will be a new reference to an otherwise equivalent Expression.
Mark