Sonntag, 22. November 2009

JUnit Rule for jMock instead of the JMock Runner

In JUnit 4.7 there is new feature called "Rules" see my previous posts...

The jMock framework comes with a JUnit 4.X runner for verifying the mock object  states after each test run. Now with rules all the stuff of the runner can be done in one rule. I have implemented an example rule based on the JMock runner (see also jMock JIRA, here is the code of my example implementation:
import org.jmock.Mockery;
import org.jmock.lib.AssertionErrorTranslator;
import org.junit.Test;
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

public class JUnitRuleMockery extends Mockery implements MethodRule {

 public JUnitRuleMockery() {
 public Statement apply(final Statement base, final FrameworkMethod method,
   Object target) {
  return new Statement() {
   public void evaluate() throws Throwable {
    try {
    } catch(Throwable exp) {
     if(!isExceptionExpectedByTestMethod(exp, method)) {
      throw exp;

 protected boolean isExceptionExpectedByTestMethod(Throwable exp, FrameworkMethod method) {
  Test test = method.getAnnotation(Test.class);
  return test.expected().equals(exp.getClass());


Example Test which use the rule:
import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

// No jMock specific Runner needed only the default JUnit runner
public class FrameworkCommandProviderTest { 
    public JUnitRuleMockery context = new JUnitRuleMockery() {{
 InternalSystemBundle mockInternalSystemBundle;
 Framework mockFramework;
 CommandInterpreter mockCommandInterpreter;
 FrameworkCommandProvider mockFrameworkCommandProvider;
 FrameworkCommandProvider frameworkCommandProvider;
 public void setUp(){
  // Create mock object for system bundle
  mockInternalSystemBundle = context.mock(InternalSystemBundle.class);
  // Mocking the getContext Method, returns always null
  context.checking(new Expectations() {{
   allowing (mockInternalSystemBundle).getContext(); will(returnValue(null));
  // Create mock object for framework
  mockFramework = context.mock(Framework.class);
  // Set the mock object system bundle into the framework mock
  mockFramework.systemBundle = mockInternalSystemBundle;
  // Create mock object for command interpreter
  mockCommandInterpreter = context.mock(CommandInterpreter.class);
  // Create mock object for the SUT class, this mock will be used to mock methods in the SUT
  mockFrameworkCommandProvider = context.mock(FrameworkCommandProvider.class);
  // Create the SUT object of type FrameworkCommandProvider
  frameworkCommandProvider = new FrameworkCommandProvider(mockFramework) {
    * Mock the SUT Method getBundleFromToken(...)
    * All method calls will delegate to a mock 
    * of the same type then the SUT object 
   protected AbstractBundle getBundleFromToken(CommandInterpreter intp, String token, boolean error) {
    // delegate the call to a mock object.
    return mockFrameworkCommandProvider.getBundleFromToken(intp, token, error);
 public void _bundle_OneArgumentsAndBundleNotFoundByToken() throws Exception { 
  final String firstToken = "myBundleName[1.0.0]";
  // Setup mock context
  context.checking(new Expectations() {{
   // one argument
   one (mockCommandInterpreter).nextArgument(); will(returnValue(firstToken));
   // next calles return null
   allowing (mockCommandInterpreter).nextArgument(); will(returnValue(null));
   // getBundleFromToken returns null
   one (mockFrameworkCommandProvider).getBundleFromToken(mockCommandInterpreter, firstToken, true);
  // invoke the _bundle() method
  throw new RuntimeException();


Keine Kommentare:

Kommentar veröffentlichen