Thursday, August 6, 2009

Checking beans properties with JMock

JMock is a great tool when you have to test how an object interacts with other objects for which you still haven't written a single line of code; all you have to do is to annotate the test class...


@RunWith(JMock.class)

...define a mockery...


private Mockery context = new JUnit4Mockery();

...and finally write a test method in which you define the mock objects you need, specify their behaviour then you execute your code and test the results:


@Test
public void testGetTable() {
System.out.println("getTable");
context.setImposteriser(ClassImposteriser.INSTANCE);
final LookupTableRepository repository = context.mock(LookupTableRepository.class);
final LookupTable table = context.mock(LookupTable.class);
final LookupTableFacadeResultFactory factory = context.mock(LookupTableFacadeResultFactory.class);
final LookupTableFacadeResult expResult = context.mock(LookupTableFacadeResult.class);

context.checking(new Expectations() {{
oneOf(repository).getTable(with(equal(tableName)));
will(returnValue(table));
oneOf(factory).make(with(equal(table)));
will(returnValue(expResult));
}});

LookupTableFacade instance = new LookupTableFacadeImpl(repository, factory);
LookupTableFacadeResult result = instance.getTable(tableName);
assertSame(expResult, result);
}

So far, so good. But what if you need to check that your object interacts with others passing as a parameter another object it has just built?

This is where custom matchers come in: you simply add an expectation that specifies that the parameter you're interested in has one property (or more) with a given value:


context.checking(new Expectations() {{
Matcher<LookupTable> tableNameMatcher = Matchers.hasProperty("tableName", equal(tableName));
oneOf(repository).save(with(tableNameMatcher));
will(returnValue(table));
oneOf(factory).make(with(equal(table)));
will(returnValue(expResult));
}});

In this example we expect our instance to ask the repository to save an object whose tableName property has the specified value.

Obviously, the matcher can be combined with others:


Matcher<LookupTableItem> codeMatcher = Matchers.hasProperty("code", equal(code));
Matcher<LookupTableItem> descriptionMatcher = Matchers.hasProperty("description", equal(description));
oneOf(repository).save(with(allOf(codeMatcher, descriptionMatcher)));
will(returnValue(table));

No comments: