Index: test/org/jmock/test/acceptance/junit4/testdata/JUnit4TestThatDoesNotDeclareAMockery.java =================================================================== --- test/org/jmock/test/acceptance/junit4/testdata/JUnit4TestThatDoesNotDeclareAMockery.java Fri Mar 20 16:41:39 GMT 2009 +++ test/org/jmock/test/acceptance/junit4/testdata/JUnit4TestThatDoesNotDeclareAMockery.java Fri Mar 20 16:41:39 GMT 2009 @@ -0,0 +1,16 @@ +package org.jmock.test.acceptance.junit4.testdata; + +import org.junit.runner.RunWith; +import org.junit.Test; +import org.jmock.integration.junit4.JMock; + +/** + * JUnitTestThatDoesNotDeclareAMockery + */ +@RunWith(JMock.class) +public class JUnit4TestThatDoesNotDeclareAMockery { + + @Test + public void aTest() { + } +} Index: test/org/jmock/test/acceptance/junit4/testdata/JUnit4TestThatDeclaresMultipleMockeries.java =================================================================== --- test/org/jmock/test/acceptance/junit4/testdata/JUnit4TestThatDeclaresMultipleMockeries.java Fri Mar 20 16:18:50 GMT 2009 +++ test/org/jmock/test/acceptance/junit4/testdata/JUnit4TestThatDeclaresMultipleMockeries.java Fri Mar 20 16:18:50 GMT 2009 @@ -0,0 +1,34 @@ +package org.jmock.test.acceptance.junit4.testdata; + +import org.jmock.Mockery; +import org.jmock.Expectations; +import org.jmock.integration.junit4.JUnit4Mockery; +import org.jmock.integration.junit4.JMock; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * JUnit4TestThatDeclaresMultipleMockeries + */ +@RunWith(JMock.class) +public class JUnit4TestThatDeclaresMultipleMockeries { + + protected Mockery context1 = new JUnit4Mockery(); + protected Mockery context2 = new JUnit4Mockery(); + private Runnable runnable1 = context1.mock(Runnable.class); + private Runnable runnable2 = context2.mock(Runnable.class); + + @Test + public void doesNotSatisfyExpectations() { + context1.checking(new Expectations() {{ + oneOf (runnable1).run(); + }}); + + context2.checking(new Expectations() {{ + oneOf (runnable2).run(); + }}); + + runnable1.run(); + } + +} Index: test/org/jmock/test/acceptance/junit4/JUnit4TestRunnerTests.java =================================================================== --- test/org/jmock/test/acceptance/junit4/JUnit4TestRunnerTests.java (revision 1351) +++ test/org/jmock/test/acceptance/junit4/JUnit4TestRunnerTests.java Fri Mar 20 16:56:22 GMT 2009 @@ -2,12 +2,7 @@ import junit.framework.TestCase; -import org.jmock.test.acceptance.junit4.testdata.DerivedJUnit4TestThatDoesNotSatisfyExpectations; -import org.jmock.test.acceptance.junit4.testdata.JUnit4TestThatDoesNotCreateAMockery; -import org.jmock.test.acceptance.junit4.testdata.JUnit4TestThatDoesNotSatisfyExpectations; -import org.jmock.test.acceptance.junit4.testdata.JUnit4TestThatDoesSatisfyExpectations; -import org.jmock.test.acceptance.junit4.testdata.JUnit4TestThatThrowsExpectedException; -import org.jmock.test.acceptance.junit4.testdata.JUnit4TestWithNonPublicBeforeMethod; +import org.jmock.test.acceptance.junit4.testdata.*; import org.jmock.test.unit.support.AssertThat; import org.junit.runner.Request; import org.junit.runner.Runner; @@ -40,7 +35,20 @@ runTest(JUnit4TestThatDoesNotCreateAMockery.class); assertTestFailedWith(IllegalStateException.class); } - + + public void testTheJUnit4TestRunnerReportsAHelpfulErrorIfThereAreMultipleMockeries() { + runTest(JUnit4TestThatDeclaresMultipleMockeries.class); + assertTestFailedWith(Exception.class); + AssertThat.stringIncludes("Should warn of multiple mockeries", "multiple Mockeries", listener.failure.getMessage()); + } + + public void testTheJUnit4TestRunnerReportsAHelpfulErrorIfThereIsNoMockery() { + runTest(JUnit4TestThatDoesNotDeclareAMockery.class); + assertTestFailedWith(Exception.class); + + AssertThat.stringIncludes("Should warn of missing mockery", "no Mockery", listener.failure.getMessage()); + } + // See issue JMOCK-156 public void testReportsMocksAreNotSatisfiedWhenExpectedExceptionIsThrown() { runTest(JUnit4TestThatThrowsExpectedException.class); @@ -53,13 +61,14 @@ AssertThat.stringIncludes("should have detected non-public before method", "Method before() should be public", listener.failure.getMessage()); } - + private void assertTestFailedWith(Class exceptionType) { assertNotNull("test should have failed", listener.failure); assertTrue("should have failed with " + exceptionType.getName() + " but threw " + listener.failure.getException(), exceptionType.isInstance(listener.failure.getException())); } - + + private void runTest(Class testClass) { Runner runner = Request.aClass(testClass).getRunner(); RunNotifier notifier = new RunNotifier(); Index: src/org/jmock/integration/junit4/JMock.java =================================================================== --- src/org/jmock/integration/junit4/JMock.java (revision 1351) +++ src/org/jmock/integration/junit4/JMock.java Fri Mar 20 16:45:41 GMT 2009 @@ -1,6 +1,8 @@ package org.jmock.integration.junit4; import java.lang.reflect.Field; +import java.util.List; +import java.util.ArrayList; import org.jmock.Mockery; import org.junit.runner.Runner; @@ -64,14 +66,27 @@ } static Field findMockeryField(Class testClass) throws InitializationError { + List mockeryFields = getMockeriesForClass(testClass); + + if (mockeryFields.isEmpty()){ + throw new InitializationError("no Mockery found in test class " + testClass); + } else if (mockeryFields.size() != 1){ + throw new InitializationError("multiple Mockeries found in test class " + testClass); + } + + return mockeryFields.get(0); + } + + private static List getMockeriesForClass(Class testClass) { + List mockeryFields = new ArrayList(); + for (Class c = testClass; c != Object.class; c = c.getSuperclass()) { for (Field field: c.getDeclaredFields()) { if (Mockery.class.isAssignableFrom(field.getType())) { - return field; + mockeryFields.add(field); } } } - - throw new InitializationError("no Mockery found in test class " + testClass); + return mockeryFields; } }