Wednesday, January 16, 2008

How to Mock an object ?

In today's article, we'll see how to build Mock objects from a normal object and what are the rules that we should follow while creating objects so that they can be mocked.

Mock objects are meant for replacing the actual domain object or an object collaborator with an 'expected' functionality. Basically here are the things we can do with a mock object.
  • We can set expectations about the object's behavior.
  • We can simulate error conditions that might occur in real life situations.
  • We can eliminate the dependency on the domain object so that we don't have
    to worry about setting up a separate environment for testing our small
    piece of code.
With that said, lets also see things we aren't supposed to do with mock object. Mock object's behavior should be restricted to its expectations. The number of objects we mock for testing a given piece of code should not be more than a small value like 2 to 3. If we have to mock too many objects to make our code work then we need to seriously consider re-factoring our code into small pieces so that we can test them using less number of mock objects.

There're again two cases you should consider while writing a mock object they are..
  • Mocking an Interface.
  • Mocking a Class

Mocking an Interface:

Creating a mock object out of a interface is very simple and straight forward. Your mock object can simply implement the interface and behave the way exactly as you expected. Lets look at an example on how to do it with a sample Interface.

Public interface Request
{

public String getParameter(String paramName);

}

Now, lets try to mock this interface

public class MockRequest implements Request
{

String _expectedValue = null;

public void setExpectedResult(String pVal)
{
this._expectedValue = pVal;
}

public String getParameter(String pName)
{
return _expectedValue;
}
}


At the first glance, you will know that my mock object has nothing to do with how the actual implementation of the Request interface gets its values from. It can get it from a simple hashmap or get it using a complex logic like going to DB, we don't care ! All we care about is what is the result that we expect from this object. This is exactly what we're doing by adding a method 'setExpectedResult()'. We just describe what we need from the mock object and nothing more.

Now in our test class we can simply write the code like this ..

public class SomeTest extends TestCase
{
public void testOneMethod()
{

MockRequest req = new MockRequest();
req.setExpectedResult("PURCHASE");

DomainObjectToTest test = new DomainObjectToTest(req);
test.callMethodTotest();

}
}

Lets assume that 'callMethodToTest()' method invokes getParameter() of the request object that is passed as a parameter to the constructor. With the mock object, we have control over what values that our code receives when it eventually calls the 'getParameter()' method on the request object.

Mocking a Class:

Mocking a class is done in pretty much the same manner as interfaces. The mock object is created by extending from the actual domain object instead of implementing an interface. The pattern to wrap a behavior around a given method remains the same as described above.

There're some rules we should follow while creating the actual domain object before we start mocking it.

  • The Domain object should be extensible. It can't be a final class.
  • The Domain object's default constructor should be visible atleast to its sub classes. So, the allowable access modifier to a default constructor is 'protected'.
  • We should not mock the very object we're trying to test in the first place.

The first two points are intuitive but I wanted to stress more on the third point here. You can check my previous article "Testing using Mock Objects using Junit", in the article I have mentioned two methods for abstracting away the singleton invocations from a given class. In one of the methods I've said that we can move the singleton invocations to a separate methods so that we can override them by returning our mock objects instead of actual singletons. This method is clearly not suggestible according to the third point I specified above. I mentioned that approach there because its easy to start off as a beginner, but the ideal way to handle that situation is always by using 'Dependency Ingestion'.

There're many other things that we can achieve and verify using the mock objects, but all those implementations are too tedious to implement manually, so we leave that to mock object generators. Mock object generators are tools to create mock objects out of real time objects, they come particularly handy while mocking interfaces. We'll discuss more about these tools in my coming articles.

Going further we'll also discuss about some famous design principles which could help us write de-coupled code while implementing a functionality. Till then, keep glued to my blog for updates !!



Powered by ScribeFire.

Tuesday, January 15, 2008

Testing using Mock objects using Junit

In today's article,we'll talk about how to test our code using Mock objects using a small example.

Lets assume a class which uses lot of singleton classes for implementing the functionality. Singleton classes if used unwisely can clutter our program with too many static invocations and make our code hard to test. For this reason we should always de-couple these singleton instances to other objects/functions. For Example consider this class...

Public class AuthorizeAdapterImpl
{

LoggerManager _logMgr = null;
DataManager _dataMgr = null;
PlanManager _planMgr = null;

public AuthorizeAdapterImpl()
{ // constructor.
}

public boolean authorizeEverything()
{
_logMgr = LoggerManager.getInstance();
_dataMgr = DataManager.getInstance();
_planMgr = PlanManager.getInstance();

....
....
....
.... // code that extensively uses these variables.

}
}

Now, if you look closely at this class it is directly dependent on three Manager classes. So in order to run/test this class we need to make sure the other Manager classes which it depends on are initialized properly, which is totally unnecessary as we wanted to test logic in only this class.

We can address this in two possible ways..
  • Replace static invocations with simple getXXXInstance methods.
  • Dependency ingestion.
Lets look at the first alternative...

Replace static invocations with simple getXXXInstance methods :

The idea behind this is to move the singleton invocations into a separate private methods so that our function doesn't directly depend on those static methods directly. Look at the code below..

Public class AuthorizeAdapterImpl

{
LoggerManager _logMgr = null;
DataManager _dataMgr = null;
PlanManager _planMgr = null;

public AuthorizeAdapterImpl()

{ // constructor.

}

public boolean authorizeEverything()
{
_logMgr = getLoggerManagerInstance();
_dataMgr = getDataManagerInstance();
_planMgr = getPlanManagerInstance();
....
....
....
.... // code that extensively uses these variables.
}

protected LoggerManager getLoggerManagerInstance()
{
return LoggerManager.getInstance();
}

protected DataManager getDataManagerInstance()
{
return DataManager.getInstance();
}

protected PlanManager getPlanManagerInstance()
{
return PlanManager.getInstance();
}
}

Now, our 'authorizeEverything()' method doesn't depend on any of the singleton classes. This class now becomes testable because we can extend this class and override the getXXXInstance() methods to return our 'Mock' objects instead of actual collaborating objects like DataManager, LoggerManager etc..

public class MockAuthorizeAdapterImpl extends AuthorizeAdapterImpl
{
protected LoggerManager getLoggerManagerInstance()
{
return new MockLoggerManager();
}

protected DataManager getDataManagerInstance()
{
return new MockDataManager();
}

protected PlanManager getPlanManagerInstance()
{
return new MockPlanManager();
}
}

Now that we have replaced the collaborating objects with our mock objects we can use this class for testing the method
'authorizeEverything()'. This works because when we call this method we're actually invoking the method in the super class which is AuthorizeAdapterImpl in this case.

Dependency Ingestion :

Dependency ingestion is a refactoring technique that allows to do the things in a more nicer and efficient way. The basic way how this differs from the above given approach is that instead of abstracting away the singleton invocations into a seperate methods in the same class, we provide the instances of these classes as 'parameters' to this method/class. The choice is again left to the developer but in this case since all the singleton objects are class level variables it makes sense to inject them at the class level instead of passing them to each method.

Public class AuthorizeAdapterImpl
{
LoggerManager _logMgr = null;
DataManager _dataMgr = null;
PlanManager _planMgr = null;

public AuthorizeAdapterImpl(LoggerManager logger, DataManager dMgr , PlanManager pMgr)

{ // constructor.
this._logMgr = logger;
this._dataMgr = dMgr;
this._planMgr = pMgr;
}

public boolean authorizeEverything()
{
//_logMgr = LoggerManager.getInstance(); We don't need this !!
//_dataMgr = DataManager.getInstance();
//_planMgr = PlanManager.getInstance();

....
....
....
.... // code that extensively uses these variables.
}

}

With this change, the code has to be changed all the invocation points where we create the object for AuthorizeAdapterImpl class to send the required objects to this class.

This makes our test class very easy to write..

public class AuthorizeAdapterImplTest
{
public void testAuthorizeEverything()
{
AuthorizeAdapterImpl impl = new AuthorizeAdapterImpl(new MockLogger(), new MockdataMgr(), new MockPlanMgr());
impl.authorizeEverything();
// assertion code to verify our test case.
}
}

There's one disadvantage with this approach...

if our AuthorizeAdapterImpl class has to use a new singleton object, then we've to change the constructor to inject that object too which may not be feasible all the times. What we can do in this case is that we'll move all these singleton objects into a container and pass the reference to the container to this class. Lets call the container DLMSubSystem. The AuthorizeAdapterImpl class becomes like this.

public class AuthorizeAdapterImpl
{

DLMSubSystem _dlmSubSystem = null;

public AuthorizeAdapterImpl(DLMSubSystem subSystem)
{
this._dlmSubSystem = subSystem;
}

public boolean authorizeEverything()
{
LoggerManager logger = _dlmSubSystem.getLogger();
DataManager dataMgr = _dlmSubSystem.getDataManager();
....
...
}
}

Well, i hope you got the basic idea behind how to use refactoring and mock objects for unit testing code. In my next article i'll tell you more about what constitutes a Mock object and how to define behavior of mock object as per our requirement.



Powered by ScribeFire.

Friday, January 11, 2008

Policies and AntiPatterns in Junit

Now that you took the first step towards the automation testing, its time to know the rules and play by them… Today, I’ll try to list down the policies that we should follow and what are the antipatterns available in Junit.

Policies:

1) Write Unit tests only for the code which is visible to other classes. You can just write tests for only the complex methods in a class, but there’s no rule of thumb for determining whether the given method is a complex method to test or not. But we can get a viable answer from the C.R.A.P formula used in Crap4J plug-in.

2) The purpose of the unit test is only to test a particular piece of code, it doesn’t make sense to implement anything more than that in a junit test case so, it should not involve complex logic like connecting to Database or setting up property files etc. You can make use of Mock objects to avoid the situations mentioned above.

3) Your unit testing code should clean you actual functionality with effective refactoring techniques, but in any case you actual code should not be changed just to make work with your Unit testing code. We should always try to make it more testable in nature, but not directly rely up on the unit testing code.

For example : You can not have logic something like this in the core part of our code..

If (isTestingMode)

//do following…

Else

// do following…

4) Mock object should be only used as a substitute of an existing object, it SHOULD NOT contain any application specific code inside it. ( Is this what we’re trying to simulate using this object ? )

For example : Lets say we've an object in the actual code that we use to fetch various property values from a property file. The method you wanted to test is written something like this...

public void methodToTest()
{
// Some application specific code
PropertyManager mgr = PropertyManager.getInstance();
String propertyName = "SomePropertyName";
String propValue = mgr.getPropertyWithName(propertyName);
// manipulating the property value here.
}

For unit testing this method, you don't need to have MyBundle.properties in the classpath, you can pull out the code which reads the property from the property file and instead pass it as an argument like this.

public void methodToTest(PropertyManager propMgr)
{
// Some application specific code
String propertyName = "SomePropertyName";
String propValue =
propMgr.getPropertyWithName(propertyName);
// manipulating the property value here.
}

Now, our code is ready for unit testing and we can mock the Propertymanager by asking it to emulate the call to 'getPropertyWithName(...)' method by returning our required values ( or behavior ). So, our mock object should look like this.

MockPropertyManager extends PropertyManager
{
public String getPropertyWithName(propertyName)
{
if(propertyName == "SomePropertyName") return "correspondingValue";
}
}

At this point, we've removed the dependency of a property file from our code. Now,we can test this code without worrying about setting up the whole environment around it.

I'll elaborate more about using mock objects in my coming articles...

Anti patterns :

Anti patterns are things we shouldn’t do or against the standard while writing any piece of code/work. We’ve antipatterns for Junit as well, and internet is filled with numerous number of articles discussing about these. As you can see, this topic is pretty dynamic in nature and new patterns are kept on adding every day.. ( well, don’t know where exactly they add, but they mention all these new items in blogs and there’re ppl who’d like to archive all these things and keep them at one single place)…

When I started looking for these things, I stumbled across one interesting article which talks especially about “Junit antipatterns”. You can just go through it and you’ll know what I’m talking about.