Channels ▼
RSS

Web Development

Testing OO Systems, Part 2: Testing Servlet Implementations


Donut Classes

Moving inside the donut, we also sometimes need to swap out objects that are used internally by the servlet — and those objects aren't conveniently passed into the servlet as arguments, as was the case with the request and response objects.

The key to providing test objects to take the place of the objects that the OUT uses is using some variant of the Factory design pattern. A Factory is an object whose job is to make other objects. The simplest possible Factory replaces

    SomeClass object = new SomeClass( "arg" );

with

class SomeClassFactory
{   public static SomeClass create( String arg )
    {   return new SomeClass( arg );
    }
}

//...

SomeClass object = SomeClassFactory.create( "arg" );

It's better, if you can, to make the Factory into an "Abstract" factory, which returns created objects in terms of the interfaces that they implement. For example, the following factory creates SomeClass objects, but the factory itself returns these objects in terms of an interface, not actual class name. That way, you can write your code in terms of interfaces, rather than concrete classes, which makes the code much more flexible. At some point in the future, you can then rewrite the factory to return some other class, and as long as that new class implements the required interface, the factory's clients don't care that the actual class that they're using has changed.

class SomeClass implements SomeInterface
{   
    boolean doSomething( );
    {   //...
    }
}

class SomeInterfaceFactory
{   public static SomeInterface create( String arg )
    {   return new SomeClass( arg );
    }
}

//...

SomeInterface object = SomeInterfaceFactory.create( "arg" );

From a testing point of view, the main advantage of a factory approach is that you can easily mock the factory's create() method. For example, given this code to test:

class ClassUnderTest
{
    public void someMethod()
    {
        SomeInterface donutObject = SomeInterfaceFactory.create("Hello");
        //...
    }
}

Our test can use PowerMock to change the class of the donutObject into something that's testable. For example, the following code changes the behavior of the earlier SomeInterfaceFactory to create mock objects rather than real ones. The mock object is defined in the first two lines (doSomething() always returns false). The next two lines change the behavior of create() to return the mockImplemenation instead of creating a normal object, and the final two lines are the actual test. someMethod() will use the mockImplemenation object.

@RunWith(PowerMockRunner.class)
@PrepareForTest( SomeInterfaceFactory.class )
public class JDBCTest extends PowerMockito
{
    @Test
    public void myTest()
    {
        SomeInterface mockImplementation = mock( SomeClass.class );
        when( mockImplementation.doSomething() ).thenReturn( false );

        mockStatic( SomeInterfaceFactory.class );
        when( SomeInterfaceFactory.create( Mockito.anyString() ).thenReturn( mockImplementation );

        //...

        ClassUnderTest objectUnderTest = new ClassUnderTest();
        objectUnderTest.someMethod();                           // uses the mock
    }
}

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV