Monday, December 1, 2008

Jmock

JMock is a library that supports test-driven development of Java code with mock objects. Mock objects help you design and test the interactions between the objects in your programs.

Let's say we are going to test class AccountService which depends on class AccountDAO to retrieve the account banlance.

class AccountService {
private AccountDao accountDao;

// set method of dao...

public double calculateInterest(long accountId){
double currentBalance = accountDao.getBalance(accountId);
return currentBalance * 0.05 ; //interest rate is 0.05
}
}

Here is the sample of testing class.
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.Expectations;

@RunWith(JMock.class)
class AccountServiceTest {
Mockery context = new JUnit4Mockery();

AccountService accountService = new AccountService();

@Test
public void oneSubscriberReceivesAMessage() {
// set up
final AccountDao accountDao = context.mock(AccountDao.class);

AccountService.setAccountDao(accountDao);

long accountId = 123L;

// expectations
context.checking(new Expectations() {
{
one(accountDao).getBalance(accountId);
will(returnValue(100)); // assuming the account balance is 100
}
});

// execute
double interest = accountService.calculateInterest(accountId);
assertEquals(5,interest);
}
}


The key here is the expectations. AccountService depends on AccountDao which is mocked in the unit testing. We only want to test the functionality of AccountService. We don't want to depend on the real AccountDao class. The expectation above means the method "getBalance" in accountDao will be invoked once with the paramter "accountId" and it will return "100" as the balance.


If you create two or more mocks of the same class you must give each mock a different name, as in
context.mock(AnyClass.class, "Mock 1");
context.mock(AnyClass.class, "Mock 2");

No comments:

Post a Comment