package org.jmock; import org.jmock.integration.junit4.JUnit4Mockery; import org.junit.Test; /** * JUnit to demonstrate a possible bug dealing with mocking a parameter passed to a mock object. */ public class JMockErrorExample { /** * Shows an error in JMock. */ @Test public void testMockErrorExample() { final Mockery context = new JUnit4Mockery(); final TestObject testObject = context.mock(TestObject.class); context.checking(new Expectations() { { // The error will occur on the next line. one(testObject).testMethod(with(same(getMockTestParameter(context)))); } }); testObject.testMethod(getMockTestParameter(context)); context.assertIsSatisfied(); } /** * Shows a workaround to the above error. */ @Test public void testMockNoErrorExample() { final Mockery context = new JUnit4Mockery(); final TestObject testObject = context.mock(TestObject.class); // Somehow, storing off the return from getMockTestParameter(Mockery) solves the problem. final TestParameter testParameter = getMockTestParameter(context); context.checking(new Expectations() { { one(testObject).testMethod(with(same(testParameter))); } }); testObject.testMethod(getMockTestParameter(context)); context.assertIsSatisfied(); } private TestParameter mockTestParameter; // We store off this guy so the getMockTestParameter(Mockery) method always returns the "same" object. /** * Creates and returns a mock TestParameter for the given {@link Mockery} context. * @param context The {@link Mockery} context for which to create the mock object (cannot be null). * @return A non-null mocked {@link TestParameter}. */ private TestParameter getMockTestParameter(final Mockery context) { if (mockTestParameter == null) { final TestParameter newMockTestParameter = context.mock(TestParameter.class); context.checking(new Expectations() { { allowing(newMockTestParameter).testMethod(); } }); mockTestParameter = newMockTestParameter; } return mockTestParameter; } /** * The parameter that will be mocked. */ private interface TestParameter { public void testMethod(); } /** * The object that will be mocked. */ private interface TestObject { public void testMethod(final TestParameter testParameter); } }