Fork me on GitHub

Tuesday, August 25, 2009

Mocks and Expressing Test Intent

Still I am stuck in the mock world. Tests have been a central part of coding life and mocks play a crucial role in them. My opinion is, test which doesn't express itself explicitly has lost its value. It may run as a part of suite but its value to the programmer as a way to understand the behavior is lost which is important.

So coming back to main topic, how mocks help in expressing your intention in test? In short mocks show a way to express constraints on how a collaborator should be used. Constraints are part of intention which in turn represent specification. Confusing as usual? Lets see an example specification and find how mock helps us to express this in our test.

Example Spec or Constraint: If I am building a Greeting application to greet in multiple languages and I use a third party translator which I need to pay for every call I make. My default language is English. So when I want greeting in English then I should not call the translator so that I don't need to pay unnecessarily.

Following is the test code I wrote for this.

public void DonotUseTranslatorWhenLanguageIsEnglish()
var translatorMock = new Mock();
translatorMock.Setup(mocktranslator => mocktranslator.Translate("English", "English", "Hello"));
var translator = translatorMock.Object;
var greeting = new Greeting(translator);
greeting.SayHello("English", "Sai");
translatorMock.Verify(tr => tr.Translate("English", "English", "Hello"), Times.Never());

The intention of this test is to see if the language is English I don't use the translator. Here I will use a mock translator because there is a constraint on its usage and I am interested in expressing this in the test. So I use a mock translator on which I set constraints of usage and then after exercising the behavior I validate if the constraint I set has been satisfied.

You may get similar constraints in your application like retry thrice for connecting with credit card processor in case of failure. Or send mail in case of critical failure in application. Such situations are really good usages of mock.

A note of caution with using mocks - Mocks are way to look into an object's working i.e. how it uses its collaborator. Unless you are really interested in this information don't use them. If your interested lies only in the behavior of the object you are trying to test, use a stub instead for a collaborator.

No comments: