Showing posts with label Unit tests. Show all posts
Showing posts with label Unit tests. Show all posts

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.

Saturday, March 6, 2010

Unit Tests and Integration tests, are they so different?

Hi there,

in my team we have lots of service side code, which connects to other services.

of course we need to write unit tests for this code, and we need integration tests also – so we will know if it actually works with the other side.

and we use Rihno mocks to test only what we want while writing UT.

our unit tests looks something like this:

[TestMethod]
public void DoAction_SendingTrueValue_MessageReturning()
{
            ILogWriter mockLogWriter =

                      (ILogWriter)mocks.CreateMock( typeof(ILogWriter));
            mockLogWriter.LogAction("");
            LastCall.Constraints(Text.Like("MyError"));
            mocks.ReplayAll();
            MyService.LogWriter = mockLogWriter;

            string message = MyService.DoAction(true);
            Assert.AreEqual("bla", message); 
}

and on the other hand, this is our integration test:

[TestMethod]
public void DoAction_SendingTrueValue_MessageReturning()
{
            string message = MyService.DoAction(true);
            Assert.AreEqual("bla", message);

}

Of course this example is extreme but the fact is that the integration tests and the unit test very often looks almost the same, the only difference is the use of a mock.

I was thinking, how can we merge the tests and  perhaps use the same code. so I read a great idea in one of the .net blogs, we can use a simple conditional compilation symbol.

we can take the first test method, and change it a little bit:

[TestMethod]
public void DoAction_SendingTrueValue_MessageReturning()
{

            #if MOCK
            ILogWriter mockLogWriter =

                      (ILogWriter)mocks.CreateMock( typeof(ILogWriter));
            mockLogWriter.LogAction("");
            LastCall.Constraints(Text.Like("MyError"));
            mocks.ReplayAll();
            MyService.LogWriter = mockLogWriter;

           #endif

            string message = MyService.DoAction(true);
            Assert.AreEqual("bla", message); 
}

than all we need is to change one definition in the project settings and change our method to be integration test,

in the project settings you can find this:

settings

if the “MOCK” word will be written there, the if in the test will return true, and the it will create a mock and work as a unit test. but if we remove the “MOCK” word, the if will return false, skip the creation of the mock and work as an integration test.

simple..

by the way, in case you didn’t understand, “MOCK” is only an example, you can write any word and write these #if symbols where ever you like.

Hope I helped – bye for now.