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.

1 comment:

  1. hey,
    sounds interesting although, I prefer not writing the same code for unit and integration.

    they are actually different, unit test your methods classes.
    while Integration is for a flow\behavior.

    I don't see any reason to run the same method twice. (if it fails as an integration, probably the name is not self explaining the behavior)

    ReplyDelete