From 03e243a4ab279cc374c454e7e021e62d6d952c8d Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 4 Feb 2014 23:14:39 +0100 Subject: [PATCH] Fix off-by-one regression in AbstractMethodMockingControl Issue: SPR-11385, SPR-10885 (cherry picked from commits 69a89b1 and 3a89bc4) --- .../AbstractMethodMockingControl.aj | 114 +++++++----- ...otationDrivenStaticEntityMockingControl.aj | 63 ++++--- .../staticmock/MockStaticEntityMethods.java | 10 +- ...nDrivenStaticEntityMockingControlTest.java | 148 --------------- ...DrivenStaticEntityMockingControlTests.java | 170 ++++++++++++++++++ .../mock/staticmock/Delegate.java | 92 ---------- 6 files changed, 290 insertions(+), 307 deletions(-) delete mode 100644 spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTest.java create mode 100644 spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTests.java delete mode 100644 spring-aspects/src/test/java/org/springframework/mock/staticmock/Delegate.java diff --git a/spring-aspects/src/main/java/org/springframework/mock/staticmock/AbstractMethodMockingControl.aj b/spring-aspects/src/main/java/org/springframework/mock/staticmock/AbstractMethodMockingControl.aj index e8fae8d097f..4661840f612 100644 --- a/spring-aspects/src/main/java/org/springframework/mock/staticmock/AbstractMethodMockingControl.aj +++ b/spring-aspects/src/main/java/org/springframework/mock/staticmock/AbstractMethodMockingControl.aj @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,16 +18,22 @@ package org.springframework.mock.staticmock; import java.util.Arrays; import java.util.LinkedList; -import java.util.List; + +import org.springframework.util.ObjectUtils; /** * Abstract aspect to enable mocking of methods picked out by a pointcut. - * Sub-aspects must define the mockStaticsTestMethod() pointcut to - * indicate call stacks when mocking should be triggered, and the - * methodToMock() pointcut to pick out a method invocations to mock. + * + *

Sub-aspects must define: + *

* * @author Rod Johnson * @author Ramnivas Laddad + * @author Sam Brannen */ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMethod()) { @@ -35,24 +41,34 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth protected abstract pointcut methodToMock(); + private boolean recording = true; - static enum CallResponse { nothing, return_, throw_ }; - // Represents a list of expected calls to static entity methods + static enum CallResponse { + nothing, return_, throw_ + }; + + /** + * Represents a list of expected calls to methods. + */ // Public to allow inserted code to access: is this normal?? public class Expectations { - // Represents an expected call to a static entity method + /** + * Represents an expected call to a method. + */ private class Call { + private final String signature; private final Object[] args; private Object responseObject; // return value or throwable private CallResponse responseType = CallResponse.nothing; - public Call(String name, Object[] args) { - this.signature = name; + + public Call(String signature, Object[] args) { + this.signature = signature; this.args = args; } @@ -77,7 +93,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth public Object throwException(String lastSig, Object[] args) { checkSignature(lastSig, args); - throw (RuntimeException)responseObject; + throw (RuntimeException) responseObject; } private void checkSignature(String lastSig, Object[] args) { @@ -88,16 +104,29 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth throw new IllegalArgumentException("Arguments don't match"); } } + + @Override + public String toString() { + return String.format("Call with signature [%s] and arguments %s", this.signature, + ObjectUtils.nullSafeToString(args)); + } } - private List calls = new LinkedList(); - // Calls already verified + /** + * The list of recorded calls. + */ + private final LinkedList calls = new LinkedList(); + + /** + * The number of calls already verified. + */ private int verified; + public void verify() { if (verified != calls.size()) { - throw new IllegalStateException("Expected " + calls.size() + " calls, received " + verified); + throw new IllegalStateException("Expected " + calls.size() + " calls, but received " + verified); } } @@ -105,31 +134,32 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth * Validate the call and provide the expected return value. */ public Object respond(String lastSig, Object[] args) { - Call call = nextCall(); - CallResponse responseType = call.responseType; - if (responseType == CallResponse.return_) { - return call.returnValue(lastSig, args); - } - else if (responseType == CallResponse.throw_) { - return call.throwException(lastSig, args); - } - else if (responseType == CallResponse.nothing) { - // do nothing + Call c = nextCall(); + + switch (c.responseType) { + case return_: { + return c.returnValue(lastSig, args); + } + case throw_: { + return c.throwException(lastSig, args); + } + default: { + throw new IllegalStateException("Behavior of " + c + " not specified"); + } } - throw new IllegalStateException("Behavior of " + call + " not specified"); } private Call nextCall() { verified++; if (verified > calls.size()) { - throw new IllegalStateException("Expected " + calls.size() + " calls, received " + verified); + throw new IllegalStateException("Expected " + calls.size() + " calls, but received " + verified); } - return calls.get(verified); + // The 'verified' count is 1-based; whereas, 'calls' is 0-based. + return calls.get(verified - 1); } - public void expectCall(String lastSig, Object lastArgs[]) { - Call call = new Call(lastSig, lastArgs); - calls.add(call); + public void expectCall(String lastSig, Object[] lastArgs) { + calls.add(new Call(lastSig, lastArgs)); } public boolean hasCalls() { @@ -137,29 +167,31 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth } public void expectReturn(Object retVal) { - Call call = calls.get(calls.size() - 1); - if (call.hasResponseSpecified()) { - throw new IllegalStateException("No static method invoked before setting return value"); + Call c = calls.getLast(); + if (c.hasResponseSpecified()) { + throw new IllegalStateException("No method invoked before setting return value"); } - call.setReturnVal(retVal); + c.setReturnVal(retVal); } public void expectThrow(Throwable throwable) { - Call call = calls.get(calls.size() - 1); - if (call.hasResponseSpecified()) { - throw new IllegalStateException("No static method invoked before setting throwable"); + Call c = calls.getLast(); + if (c.hasResponseSpecified()) { + throw new IllegalStateException("No method invoked before setting throwable"); } - call.setThrow(throwable); + c.setThrow(throwable); } } - private Expectations expectations = new Expectations(); + + private final Expectations expectations = new Expectations(); + after() returning : mockStaticsTestMethod() { if (recording && (expectations.hasCalls())) { throw new IllegalStateException( - "Calls recorded, yet playback state never reached: Create expectations then call " - + this.getClass().getSimpleName() + ".playback()"); + "Calls recorded, yet playback state never reached: Create expectations then call " + + this.getClass().getSimpleName() + ".playback()"); } expectations.verify(); } diff --git a/spring-aspects/src/main/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControl.aj b/spring-aspects/src/main/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControl.aj index 816f6a1e424..a9985e9c7e4 100644 --- a/spring-aspects/src/main/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControl.aj +++ b/spring-aspects/src/main/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControl.aj @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,50 +17,69 @@ package org.springframework.mock.staticmock; /** - * Annotation-based aspect to use in test build to enable mocking static methods - * on JPA-annotated {@code @Entity} classes, as used by Roo for finders. + * Annotation-based aspect to use in test builds to enable mocking of static methods + * on JPA-annotated {@code @Entity} classes, as used by Spring Roo for so-called + * finder methods. * - *

Mocking will occur in the call stack of any method in a class (typically a test class) - * that is annotated with the @MockStaticEntityMethods annotation. + *

Mocking will occur within the call stack of any method in a class (typically a + * test class) that is annotated with {@code @MockStaticEntityMethods}. * - *

Also provides static methods to simplify the programming model for - * entering playback mode and setting expected return values. + *

This aspect also provides static methods to simplify the programming model for + * setting expectations and entering playback mode. * *

Usage: *

    - *
  1. Annotate a test class with @MockStaticEntityMethods. - *
  2. In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode. - * Invoke static methods on Entity classes, with each recording-mode invocation - * being followed by an invocation to the static expectReturn() or expectThrow() - * method on AnnotationDrivenStaticEntityMockingControl. - *
  3. Invoke the static AnnotationDrivenStaticEntityMockingControl() method. - *
  4. Call the code you wish to test that uses the static methods. Verification will - * occur automatically. + *
  5. Annotate a test class with {@code @MockStaticEntityMethods}. + *
  6. In each test method, {@code AnnotationDrivenStaticEntityMockingControl} + * will begin in recording mode. + *
  7. Invoke static methods on JPA-annotated {@code @Entity} classes, with each + * recording-mode invocation being followed by an invocation of either the static + * {@link #expectReturn(Object)} method or the static {@link #expectThrow(Throwable)} + * method on {@code AnnotationDrivenStaticEntityMockingControl}. + *
  8. Invoke the static {@link #playback()} method. + *
  9. Call the code you wish to test that uses the static methods. + *
  10. Verification will occur automatically. *
* * @author Rod Johnson * @author Ramnivas Laddad + * @author Sam Brannen * @see MockStaticEntityMethods */ public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl { /** - * Stop recording mock calls and enter playback state + * Expect the supplied {@link Object} to be returned by the previous static + * method invocation. + * @see #playback() */ - public static void playback() { - AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal(); - } - public static void expectReturn(Object retVal) { AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal); } + /** + * Expect the supplied {@link Throwable} to be thrown by the previous static + * method invocation. + * @see #playback() + */ public static void expectThrow(Throwable throwable) { AnnotationDrivenStaticEntityMockingControl.aspectOf().expectThrowInternal(throwable); } - // Only matches directly annotated @Test methods, to allow methods in - // @MockStatics classes to invoke each other without resetting the mocking environment + /** + * Stop recording mock expectations and enter playback mode. + * @see #expectReturn(Object) + * @see #expectThrow(Throwable) + */ + public static void playback() { + AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal(); + } + + // Apparently, the following pointcut was originally defined to only match + // methods directly annotated with @Test (in order to allow methods in + // @MockStaticEntityMethods classes to invoke each other without resetting + // the mocking environment); however, this is no longer the case. The current + // pointcut applies to all public methods in @MockStaticEntityMethods classes. protected pointcut mockStaticsTestMethod() : execution(public * (@MockStaticEntityMethods *).*(..)); protected pointcut methodToMock() : execution(public static * (@javax.persistence.Entity *).*(..)); diff --git a/spring-aspects/src/main/java/org/springframework/mock/staticmock/MockStaticEntityMethods.java b/spring-aspects/src/main/java/org/springframework/mock/staticmock/MockStaticEntityMethods.java index 913d147b3e1..f68b80640b8 100644 --- a/spring-aspects/src/main/java/org/springframework/mock/staticmock/MockStaticEntityMethods.java +++ b/spring-aspects/src/main/java/org/springframework/mock/staticmock/MockStaticEntityMethods.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,11 +22,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Annotation to indicate a test class for whose @Test methods - * static methods on Entity classes should be mocked. See - * {@code AbstractMethodMockingControl}. + * Annotation to indicate a test class for whose {@code @Test} methods + * static methods on JPA-annotated {@code @Entity} classes should be mocked. + * + *

See {@link AnnotationDrivenStaticEntityMockingControl} for details. * * @author Rod Johnson + * @author Sam Brannen */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) diff --git a/spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTest.java b/spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTest.java deleted file mode 100644 index 5a531301c9a..00000000000 --- a/spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.mock.staticmock; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.expectReturn; -import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.expectThrow; -import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.playback; - -import javax.persistence.PersistenceException; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - - -/** - * Test for static entity mocking framework. - * @author Rod Johnson - * @author Ramnivas Laddad - * - */ -@MockStaticEntityMethods -@RunWith(JUnit4.class) -public class AnnotationDrivenStaticEntityMockingControlTest { - - @Test - public void testNoArgIntReturn() { - int expectedCount = 13; - Person.countPeople(); - expectReturn(expectedCount); - playback(); - assertEquals(expectedCount, Person.countPeople()); - } - - @Test(expected=PersistenceException.class) - public void testNoArgThrows() { - Person.countPeople(); - expectThrow(new PersistenceException()); - playback(); - Person.countPeople(); - } - - @Test - public void testArgMethodMatches() { - long id = 13; - Person found = new Person(); - Person.findPerson(id); - expectReturn(found); - playback(); - assertEquals(found, Person.findPerson(id)); - } - - - @Test - public void testLongSeriesOfCalls() { - long id1 = 13; - long id2 = 24; - Person found1 = new Person(); - Person.findPerson(id1); - expectReturn(found1); - Person found2 = new Person(); - Person.findPerson(id2); - expectReturn(found2); - Person.findPerson(id1); - expectReturn(found1); - Person.countPeople(); - expectReturn(0); - playback(); - - assertEquals(found1, Person.findPerson(id1)); - assertEquals(found2, Person.findPerson(id2)); - assertEquals(found1, Person.findPerson(id1)); - assertEquals(0, Person.countPeople()); - } - - // Note delegation is used when tests are invalid and should fail, as otherwise - // the failure will occur on the verify() method in the aspect after - // this method returns, failing the test case - @Test - public void testArgMethodNoMatchExpectReturn() { - try { - new Delegate().testArgMethodNoMatchExpectReturn(); - fail(); - } catch (IllegalArgumentException expected) { - } - } - - @Test(expected=IllegalArgumentException.class) - public void testArgMethodNoMatchExpectThrow() { - new Delegate().testArgMethodNoMatchExpectThrow(); - } - - private void called(Person found, long id) { - assertEquals(found, Person.findPerson(id)); - } - - @Test - public void testReentrant() { - long id = 13; - Person found = new Person(); - Person.findPerson(id); - expectReturn(found); - playback(); - called(found, id); - } - - @Test(expected=IllegalStateException.class) - public void testRejectUnexpectedCall() { - new Delegate().rejectUnexpectedCall(); - } - - @Test(expected=IllegalStateException.class) - public void testFailTooFewCalls() { - new Delegate().failTooFewCalls(); - } - - @Test - public void testEmpty() { - // Test that verification check doesn't blow up if no replay() call happened - } - - @Test(expected=IllegalStateException.class) - public void testDoesntEverReplay() { - new Delegate().doesntEverReplay(); - } - - @Test(expected=IllegalStateException.class) - public void testDoesntEverSetReturn() { - new Delegate().doesntEverSetReturn(); - } -} - diff --git a/spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTests.java b/spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTests.java new file mode 100644 index 00000000000..4993fbc2970 --- /dev/null +++ b/spring-aspects/src/test/java/org/springframework/mock/staticmock/AnnotationDrivenStaticEntityMockingControlTests.java @@ -0,0 +1,170 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.mock.staticmock; + +import java.rmi.RemoteException; + +import javax.persistence.PersistenceException; + +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl.*; + +/** + * Tests for Spring's static entity mocking framework (i.e., @{@link MockStaticEntityMethods} + * and {@link AnnotationDrivenStaticEntityMockingControl}). + * + * @author Rod Johnson + * @author Ramnivas Laddad + * @author Sam Brannen + */ +@MockStaticEntityMethods +public class AnnotationDrivenStaticEntityMockingControlTests { + + @Test + public void noArgumentMethodInvocationReturnsInt() { + int expectedCount = 13; + Person.countPeople(); + expectReturn(expectedCount); + playback(); + assertEquals(expectedCount, Person.countPeople()); + } + + @Test(expected = PersistenceException.class) + public void noArgumentMethodInvocationThrowsException() { + Person.countPeople(); + expectThrow(new PersistenceException()); + playback(); + Person.countPeople(); + } + + @Test + public void methodArgumentsMatch() { + long id = 13; + Person found = new Person(); + Person.findPerson(id); + expectReturn(found); + playback(); + assertEquals(found, Person.findPerson(id)); + } + + @Test + public void longSeriesOfCalls() { + long id1 = 13; + long id2 = 24; + Person found1 = new Person(); + Person.findPerson(id1); + expectReturn(found1); + Person found2 = new Person(); + Person.findPerson(id2); + expectReturn(found2); + Person.findPerson(id1); + expectReturn(found1); + Person.countPeople(); + expectReturn(0); + playback(); + + assertEquals(found1, Person.findPerson(id1)); + assertEquals(found2, Person.findPerson(id2)); + assertEquals(found1, Person.findPerson(id1)); + assertEquals(0, Person.countPeople()); + } + + @Test(expected = IllegalArgumentException.class) + public void methodArgumentsDoNotMatchAndReturnsObject() { + long id = 13; + Person found = new Person(); + Person.findPerson(id); + AnnotationDrivenStaticEntityMockingControl.expectReturn(found); + AnnotationDrivenStaticEntityMockingControl.playback(); + assertEquals(found, Person.findPerson(id + 1)); + } + + @Test(expected = IllegalArgumentException.class) + public void methodArgumentsDoNotMatchAndThrowsException() { + long id = 13; + Person found = new Person(); + Person.findPerson(id); + AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException()); + AnnotationDrivenStaticEntityMockingControl.playback(); + assertEquals(found, Person.findPerson(id + 1)); + } + + @Test + public void reentrant() { + long id = 13; + Person found = new Person(); + Person.findPerson(id); + expectReturn(found); + playback(); + called(found, id); + } + + private void called(Person found, long id) { + assertEquals(found, Person.findPerson(id)); + } + + @Test(expected = IllegalStateException.class) + public void rejectUnexpectedCall() { + AnnotationDrivenStaticEntityMockingControl.playback(); + Person.countPeople(); + } + + @Test(expected = IllegalStateException.class) + public void tooFewCalls() { + long id = 13; + Person found = new Person(); + Person.findPerson(id); + AnnotationDrivenStaticEntityMockingControl.expectReturn(found); + Person.countPeople(); + AnnotationDrivenStaticEntityMockingControl.expectReturn(25); + AnnotationDrivenStaticEntityMockingControl.playback(); + assertEquals(found, Person.findPerson(id)); + } + + @Test + public void empty() { + // Test that verification check doesn't blow up if no replay() call happened. + } + + @Test(expected = IllegalStateException.class) + public void doesNotEnterPlaybackMode() { + Person.countPeople(); + } + + @Test(expected = IllegalStateException.class) + public void doesNotSetExpectedReturnValue() { + Person.countPeople(); + AnnotationDrivenStaticEntityMockingControl.playback(); + } + + /** + * Note: this test method currently does NOT actually verify that the mock + * verification fails. + */ + // TODO Determine if it's possible for a mock verification failure to fail a test in + // JUnit 4+ if the test method itself throws an expected exception. + @Test(expected = RemoteException.class) + public void verificationFailsEvenWhenTestFailsInExpectedManner() throws Exception { + Person.countPeople(); + AnnotationDrivenStaticEntityMockingControl.playback(); + // No calls in order to allow verification failure + throw new RemoteException(); + } + +} diff --git a/spring-aspects/src/test/java/org/springframework/mock/staticmock/Delegate.java b/spring-aspects/src/test/java/org/springframework/mock/staticmock/Delegate.java deleted file mode 100644 index d4b3206bc36..00000000000 --- a/spring-aspects/src/test/java/org/springframework/mock/staticmock/Delegate.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.mock.staticmock; - -import static org.junit.Assert.assertEquals; - -import java.rmi.RemoteException; - -import javax.persistence.PersistenceException; - -import org.junit.Ignore; -import org.junit.Test; -import org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl; -import org.springframework.mock.staticmock.MockStaticEntityMethods; - -//Used because verification failures occur after method returns, -//so we can't test for them in the test case itself -@MockStaticEntityMethods -@Ignore // This isn't meant for direct testing; rather it is driven from AnnotationDrivenStaticEntityMockingControl -public class Delegate { - - @Test - public void testArgMethodNoMatchExpectReturn() { - long id = 13; - Person found = new Person(); - Person.findPerson(id); - AnnotationDrivenStaticEntityMockingControl.expectReturn(found); - AnnotationDrivenStaticEntityMockingControl.playback(); - assertEquals(found, Person.findPerson(id + 1)); - } - - @Test - public void testArgMethodNoMatchExpectThrow() { - long id = 13; - Person found = new Person(); - Person.findPerson(id); - AnnotationDrivenStaticEntityMockingControl.expectThrow(new PersistenceException()); - AnnotationDrivenStaticEntityMockingControl.playback(); - assertEquals(found, Person.findPerson(id + 1)); - } - - @Test - public void failTooFewCalls() { - long id = 13; - Person found = new Person(); - Person.findPerson(id); - AnnotationDrivenStaticEntityMockingControl.expectReturn(found); - Person.countPeople(); - AnnotationDrivenStaticEntityMockingControl.expectReturn(25); - AnnotationDrivenStaticEntityMockingControl.playback(); - assertEquals(found, Person.findPerson(id)); - } - - @Test - public void doesntEverReplay() { - Person.countPeople(); - } - - @Test - public void doesntEverSetReturn() { - Person.countPeople(); - AnnotationDrivenStaticEntityMockingControl.playback(); - } - - @Test - public void rejectUnexpectedCall() { - AnnotationDrivenStaticEntityMockingControl.playback(); - Person.countPeople(); - } - - @Test(expected=RemoteException.class) - public void testVerificationFailsEvenWhenTestFailsInExpectedManner() throws RemoteException { - Person.countPeople(); - AnnotationDrivenStaticEntityMockingControl.playback(); - // No calls to allow verification failure - throw new RemoteException(); - } -}