Sunday, June 5, 2011

Short introduction to jMock

The jUnit framework is a great tool for testing your Java application. But writing test cases can be complex. Especially when the object under test is dependent on several other objects, which in turn depend on other objects. This means the whole dependency graph has to be created before the test can be executed. Building this graph can be complex, and error-prone.

Luckily for us, there exists a framework called jMock. jMock enables you to create mock objects that mimic behavior of dependent objects. We can configure the expected interaction and behavior of these objects.

Let's start with an example class we want to test:

package com.javaeenotes;

public class TestSubject {
private DependentClassInterface depObject;

public TestSubject(DependentClassInterface depObject) {
this.depObject = depObject;
}

public String method() {
return depObject.method();
}
}

The class is dependent on a class with the following interface:

package com.javaeenotes;

public interface DependentClassInterface {
public String method();
}

The interface specifies a method that returns a String. The actual implementation of this interface is not required for jMock. jMock uses the interface to create an object with the same interface you can use in your test cases.

An example test case:

package com.javaeenotes;

import static org.junit.Assert.assertTrue;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;

public class TestSubjectTest {
@Test
public void testMethod() {
Mockery context = new Mockery();
// Create mock object.
final DependentClassInterface depObject = context
.mock(DependentClassInterface.class);

// Test object is instantiated with mock object.
TestSubject testSubject = new TestSubject(depObject);

// Configure expectation and behavior.
context.checking(new Expectations() {
{
oneOf(depObject).method();
will(returnValue("hello"));
}
});

// Test outcome.
assertTrue(testSubject.method().equals("hello"));

// Check if expectations are satisfied.
context.assertIsSatisfied();

}
}

In this test case, we create the object under test with a mock object. The expected interaction and behavior is then configured. First, the method() method is called, which then returns a string value "hello". Other interactions, like calling the same method twice, will result in an error.

As you can see, jMock is a very valuable extension to the jUnit framework, which makes writing test cases much easier.

Links:


Note: when running jMock in Eclipse, the following error can occur when running test cases:

java.lang.SecurityException:
class "org.hamcrest.TypeSafeMatcher"'s signer information
does not match signer information of other classes in the
same package

The solution is make sure the jMock libraries are included before the standard jUnit libraries in the build path.

No comments:

Post a Comment