Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Unit Test More Efficiently with Mock Object Alternatives : Page 4

The mock-object testing pattern has commonly been used to test an individual unit of code without testing its dependencies. While this pattern works well for interaction-based testing, it can be overkill for state-based testing. Learn how to streamline your unit-testing using stubs and the pseudo-objects testing pattern.


advertisement
Passing in Mocks and Pseudos
It's often difficult to test methods that are responsible for their own object creation. If a method is responsible for creating the objects that it uses, then the method cannot be tested with substituted objects such as mock and stubs. The method must be refactored to separate the creation of the objects from the operations on those objects.

There are two primary refactorings that I have seen used to solve this problem. They both attempt to separate creational and behavioral functionality. This section starts with a simple example, and then you'll walk through both refactoring strategies so that you can see the resulting code and corresponding unit test.

The first refactoring strategy is documented in an article on IBM DeveloperWorks by Alex Chaffee and William Pietri. In their article's example, you have a run() method that creates and uses a View object:



public class Application { public void run() { View v = new View(); v.display(); } }

The article demonstrates testing the run method by refactoring the code through extracting a factory method:

public class Application { public void run() { View v = createView(); v.display(); } protected View createView() { return new View(); } }

Next, you can write a testcase that overrides the createView() method and passes in a mock or a stub instead.

class ApplicationTest extends TestCase { private MockView mockView = new MockView(); public void testApplication() { Application a = new Application() { protected View createView() { return mockView; } }; a.run(); mockView.validate(); } }

When the run() method is called, the MockView is used instead of the real View object. This allows you to substitute mock objects for real objects, but not without a cost:
  • You can't make your class final because the test class needs to override it.
  • You have to create a new factory method for every single object that the method under test needs to use.
A second and slightly simpler way to test this is to start with a simple refactoring for the original Application class:

public class Application { public void run() { run(new View()); } // package private for testing only void run(View view) { view.display(); } }

Make the public run method a pass-through to a package-private run method. The public run method will still be called by production code in the same exact way, though it doesn't do anything besides create the real View object and pass it in to the package-private run method. The package-private run method operates on the objects, but is free of creational responsibilities. This method remains package-private so that the test class can access it.

Here is the test:

class ApplicationTest extends TestCase { private MockView mockView = new MockView(); public void testApplication() { Application application = new Application(); application.run(mockView); mockView.validate(); } }

Now, all you have to do is test the package-private run method that takes a parameter. The test is focused on just the behavioral aspect of the class. You don't have to override anything, and you can make the class final if you so desire. If the run method needs more than one object, simply make the public run method create multiple objects, and make the "testable" run method take multiple arguments. There is no need to test the run method that takes no parameters because it has no behavioral responsibilities that need testing.

Another method of accomplishing the same thing is to make the client code responsible for creating the objects. You can achieve this by creating all the necessary objects in the client code and then passing them in through either the constructor or through setter methods. This is often referred to as dependency injection. There are dependency injection frameworks that make this job easy. I have written a two-part article on a dependency injection framework called Spring. The articles can be found here on DevX:

Spring: Creating Objects So You Don't Have To
Simplify Your Web App Development Using the Spring MVC Framework



Javid Jamae consults for Valtech, a global consulting group specializing in delivering advanced technology solutions. Valtech endeavors to help its customers through its global delivery model to create and/or maintain an affordable competitive advantage.
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap