Friday, December 3, 2010

Comparing Lambda expression in unit tests

A couple of days ago i had an interesting debug session at work.

Some guy try to test a method that gets a lambda expression as a parameter. he tried to create a stub for the method but had some difficulties.

The code looked like this:

public class MyClass
{
    public int MyMethod(Expression<Func<int,bool>> expression)
    {
      //Do something
    }
}

....

[Test]
public void MyMethodTest()
{
    var myStub = MockRepository.GenerateStub<MyClass>();
    myStub.Stub(x=> x.MyMethod(y=>y==3)).Return(10);
    myStub.MyMethod(y=>y==3);
}

The problem was that when the code tried to run MyMethod he didn't recognized the stub because the lambda expressions was not equal… why? because the default "Equals" compare references.

To solve the problem we started by searching for something that will help us identify in a unique way lambda expressions.

If you have read my post about expression trees you will know that an Expression object has the following properties:

1)Body - the expression
2)Parameters
3)NodeType - LambdaExpression
4)Type - Func<int, bool>

The only thing that identify the expression is the body, which is an expression itself. so the solution was not here.

The Only solution we thought of is to implement the Equals ourselves(as we let re-sharper do it for us in our  own entities), but we didn't know how. we searched for some Constraints and we found the following solution which was exactly what we needed:

myStub.Stub(x=>x.MyMethod(Arg<Expression<Func<in,bool>>>.Matches(Property.AllPropertiesMatch(y=>y==3))).Return(10);

The constraint Property.AllPropertiesMatch does the trick and compare the expression by it's properties.

Note: the expression y=>y==3 does not equals to x=>x==3!

*This post is dedicated to Jones,that gave me an interesting afternoon of debugging and coding.

No comments:

Post a Comment