Mockery

Featured image

Mocking - Introduction

Objects are first rate citizens in the Java society. Like a typical society the Java world has different flavors of objects each performing its own function. The Single Responsibility principle (SRP) states that objects should perform one single responsibility to ensure maximum re-use. This principle, however sociologically sound poses huge testing challenges. The problem with it is that objects can no longer be tested in isolation. The entire dependency tree of objects needs to be materialized before an object can be tested. Mocks are an attempt in the direction of faking object dependencies. The object being tested can be tested by mocking its immediate dependencies. mockery.jpg In the diagram above, for the object A to be tested, we need to materialize the entire chain of dependencies which means we need to create classes B,C,D and E. If one of the objects tested relies on the services of a container, then it becomes harder to test in the absence of a container. Mock objects serve the following needs:

Strategies for Mocking

Writing Testable Classes.

A class that can be tested with mocks should be testable. This means that it has to allow the user of the class to replace an implementation of its dependencies with mock dependencies. Conside the following class:

public class A {
public void foo(){
B b = new B();
// do something with B
}
}

This class is very difficult to test with mocks because it is instantiating B within a method. Hence we cannot replace B with a mocked instance of B. To make this class testable it can be coded as follows:

public class A {

public void foo(){
B b = createB();
// do something with B
}

protected B createB() {
return new B();
}
}

This version of the class is better but still not perfect. The reason that it is better is because it is possible to instantiate a sub class of A with the createB() method over-ridden.

    
    public class TestA extends TestCase {
    public void testFoo() {
    A a = createA();
    a.foo();
    }
    
    public A createA(){
    return new A(){
    // over-ride createB() method in class A
    protected B createB() {
    // create a mock version of B and return.
    }
    }
    }
    }

The version of A that would be the most testable would be the one where B’s interface is used instead of the actual class B. The most testable objects are the ones that use principles such as IOC (Inversion of Control) to facilitate the injection of dependencies in them.

How do mocks work

So what exactly is this mock object all about? How does it ape what other objects do? They say “monkey say monkey do” and this is applicable to mocks as well. The following steps need to be followed in using mocks:

Create the mock object.

If the object to be mocked is a class(as opposed to an interface), it is possible that we might have to provide constructor arguments and values for using non default constructors.

Set the expectation.

This means that the mock object might have to be told as to what methods in it will be called, how many times they will be called and in what order. We also need to specify with what arguments the function would be called and how to match these arguments with the actual arguments passed. Ex: Consider the following class:

    
    
    public class ClassToBeMocked {
    public ClassToBeMocked(String arg0){
    }
     
    
    public String method1(int arg0, String arg1) {
    --
    }
    
    public int method2(String arg0){
    --
    }
    }
    

This class needs a String argument to be instantiated. Accordingly that needs to be passed during the creation of the mock object phase. In the set expectation stage, we can indicate that method1 would be called exactly once with arguments 10 and “foo” and method2 would be called twice exactly with arguments “bar”. The way these expectations are set differs from one framework to another. The [JMock|http://www.jmock.org/getting-started.html] framework gives extensive control on argument matching. For instance, see the [constraints|http://www.jmock.org/constraints.html] that can be set.

Set return Values

In this phase, we tell the mock object what value to return when the constraint is actually called. For instance, in the above example we can specify the mock object to return the string “John Doe” when method1 is called with arguments 20 and “foo”. We should also be able to say here that method1 should always return the string “John Doe” no matter what arguments are passed to it.

Actually execute the tests using the mock objects.

At this stage, the actual tests are run.

Verification

The mock objects may be explicitly called at this stage to verify if indeed they have been called with the correct number of arguments in the order specified.

The Denizens of the Mockery Zoo

A lot of frameworks exist for writing mocks. All of them rely on method interception which is achieved in Java in a couple of ways:

Comments

Daisy: Hi Is there any way that I can pass constructor arguments while creating the Mock Objects using Jmock 2.X? If no, How can we pass the arguments of the constructor then? Thanks in advance Daisy

raja shankar kolluru: @Daisy.. it has been a while since i wrote this article and hence to answer your question, I would have to do exactly what I would advocate you to do which is to look up the documentation. But JMock, i remember during that time, was an excellent framework and hence should support object creation using constructors as well as injection of dependencies using setter based strategies. But does JMock 2.x support it? Unfortunately, i can't offhand answer that. But would love to see an update from you based on your research. Thanks