Home Blog Trade-offs in Unit Testing – Part III Stub Objects

Trade-offs in Unit Testing – Part III Stub Objects

Poornima
Founder, Femgineer
· June 8, 2008 · 3 min read

I understand that no one likes to write test cases. For most developers its tied with debugging as their least favorite activity, because they …

I understand that no one likes to write test cases. For most developers its tied with debugging as their least favorite activity, because they just want to focus on algorithms, and writing code; thats the fun stuff. But I don’t think developers understand the importance of writing test cases. The more test cases you write the more time you have to develop! I know it sounds counter-intuitive. But the reasoning is the more test cases you write, the fewer bugs you have to fix, which also means less time spent debugging as well! Writing quality code frees up time to work on more new and exciting projects.

Recently at Mint I noticed I was getting bombarded with bugs everyday I walked into the office. And they were all for features that I had written over 6 months ago! But I hadn’t bothered to test them out, because I was being assigned new feature requests everyday, and writing code for new features was much more glamorous to writing test cases for old features. So one evening I decided enough is enough! I was tired of sitting in my cube every week and devoting more than half a day to fixing and debugging bugs! What was my solution? Unit-testing using stubs. I took each key feature that I was responsible for a created a test suite for them. For each suite I outlined the basic unit test cases, corner cases, and test cases for bugs I had experienced. My next dilemma was how to write the unit test cases without needing a Spring Application Context, and without needing to generate test data or use a database… enter Stubs.

When you have a code base as large as Mint’s you are bound to run into some interdependencies even when unit testing. But the principle of unit testing is to focus on one or a limited number of classes or key functionality. The best way to do this is to use a stub. A stub acts as a substitute for another class. The easiest way to implement it is to extend a parent class or implement an interface, and then provide a basic implementation of the class by specifying simple return values for the methods (i.e. there is hardly any logic in the methods). You then replace the class-under-test’s dependency with a stub class.

For example, all my Alert classes had a dependence to an AlertDao class (the AlertDao class is the class that stores data base objects). Since I didn’t want to my unit test cases to depend on a data base I abstracted away the AlertDao Class using an AlertDaoStub. The AlertDaoStub contained the same methods as the AlertDao, but they methods had very simple return values. In place of using an AlertDao I used the AlertDaoStub; this change was transparent to the Alert class.

e.g. Implementation of the Stub class

// class-under-test
AlertManager am = new AlertManager();
// stub class that extends a parent class
AlertDao ad = new AlertDaoStub();
// replace AlertDao with AlertDaoStub
am.setAlertDao(ad);

public class AlertManager {
private AlertDao _myAlertDao;

public void setAlertDao(AlertDao ad) {
this._myAlertDao = ad;
}
}

// This can either be a public class or a private inner class depending on how much it needs to

// be re-used

public class AlertDaoStub extends AlertDao {

public Set<Alert> getAlerts(User u) {
return new HashSet<Alert>();
}

public void setAlerts(User u, Set<Alert> alerts) {
user.setAlerts(alerts);
}
}

While this technique required some refactoring, and one long night of coding, I believe in the long run I will have contributed to the quality of the Mint code base, and saved myself countless hours of debugging.

Enhanced by Zemanta
Pocket
Share on reddit
Share on LinkedIn
Bookmark this on Digg

← Part II - Trade-off to using… All posts Performance: Part I Develop a Monitoring… →