Search code examples
javaunit-testingjmock

JMock static Mockery vs. local Mockery


We have a large number of unit tests written using JMock 2.5.1 and most (all?) of them use local Mockery object such as:

@RunWith(JMock.class)
public class SomeTestClass {

    private Mockery context;

    @Before
    public void setUp() {
        context = new Mockery();
    }
}

We decided to upgrade to JMock 2.8.3 so that we could use new features, such as thread safe mocks. However, with the existing unit tests running under 2.8.3, I get:

Testcase: testReordering_GoingUp(com.hcs.orc.board.NameTagList2Test):   Caused an ERROR
Mockery named 'context' is null
java.lang.IllegalStateException: Mockery named 'context' is null
    at org.jmock.integration.junit4.JMock.mockeryOf(JMock.java:67)
    at org.jmock.integration.junit4.JMock.createTest(JMock.java:35)

It seems that JMock 2.8.3 requires a static version of the Mockery. That is:

@RunWith(JMock.class)
public class SomeTestClass {

    public static Mockery context;

    @BeforeClass
    public static void globalSetUp() {
        context = new Mockery();
    }
}

However, this creates bleed over in the Mockery between tests. That is the previously created mock objects still exist even after the test resulting in errors such as:

a mock with name fullScreenFrame already exists
java.lang.IllegalArgumentException: a mock with name fullScreenFrame already exists
    at org.jmock.Mockery.mock(Mockery.java:128)
    at org.jmock.Mockery.mock(Mockery.java:120)

Is there a way to upgrade from JMock 2.5.1 to JMock 2.8.3 without reworking 100s (1000s?) of unit tests?

NOTE: Edited to reflect moving to JMock 2.8.3. JMock 2.6.1 is not the latest code, despite what jmock.org's very out of date and unmaintained website says.


Solution

  • The workaround I settled on, was between my first pass and @Foxsly's answer. It allows me to move to JMock 2.8.3 without rewritting more than my declaration of the Mockery (and remove the @RunWith).

    public class SomeTestClass {
    
       @Rule
       public JUnitRuleMockery context = new JUnitRuleMockery();
    
       private SomeOtherClass fullScreenFrame;
    
       @Before
       public void setUp() {
           fullScreenFrame = context.mock(SomeOtherClass.class);
       }
    }