summaryrefslogtreecommitdiff
path: root/tests/com/google/testing/littlemock/LittleMockTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/com/google/testing/littlemock/LittleMockTest.java')
-rw-r--r--tests/com/google/testing/littlemock/LittleMockTest.java596
1 files changed, 420 insertions, 176 deletions
diff --git a/tests/com/google/testing/littlemock/LittleMockTest.java b/tests/com/google/testing/littlemock/LittleMockTest.java
index 9d3cf38..e8c7b1e 100644
--- a/tests/com/google/testing/littlemock/LittleMockTest.java
+++ b/tests/com/google/testing/littlemock/LittleMockTest.java
@@ -42,6 +42,7 @@ import static com.google.testing.littlemock.LittleMock.isA;
import static com.google.testing.littlemock.LittleMock.mock;
import static com.google.testing.littlemock.LittleMock.never;
import static com.google.testing.littlemock.LittleMock.reset;
+import static com.google.testing.littlemock.LittleMock.timeout;
import static com.google.testing.littlemock.LittleMock.times;
import static com.google.testing.littlemock.LittleMock.verify;
import static com.google.testing.littlemock.LittleMock.verifyNoMoreInteractions;
@@ -50,16 +51,18 @@ import static com.google.testing.littlemock.LittleMock.verifyZeroInteractions;
import junit.framework.TestCase;
import java.io.IOException;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
/**
* Unit tests for the LittleMock class.
@@ -67,16 +70,6 @@ import java.util.concurrent.Callable;
* @author hugohudson@gmail.com (Hugo Hudson)
*/
public class LittleMockTest extends TestCase {
- /**
- * Used in these unit tests to indicate that the method should throw a given type of exception.
- */
- @Target({ ElementType.METHOD })
- @Retention(RetentionPolicy.RUNTIME)
- public @interface ShouldThrow {
- public Class<? extends Throwable> value();
- public String[] messages() default {};
- }
-
@Mock private Foo mFoo;
@Mock private Bar mBar;
@Mock private BarSubtype mBarSubtype;
@@ -84,36 +77,20 @@ public class LittleMockTest extends TestCase {
@Captor private ArgumentCaptor<String> mCaptureAnotherString;
@Captor private ArgumentCaptor<Integer> mCaptureInteger;
@Captor private ArgumentCaptor<Callback> mCaptureCallback;
+ private ExecutorService mExecutorService;
@Override
protected void setUp() throws Exception {
super.setUp();
LittleMock.initMocks(this);
+ mExecutorService = Executors.newCachedThreadPool();
}
@Override
- protected void runTest() throws Throwable {
- Method method = getClass().getMethod(getName(), (Class[]) null);
- ShouldThrow shouldThrowAnnotation = method.getAnnotation(ShouldThrow.class);
- if (shouldThrowAnnotation != null) {
- try {
- super.runTest();
- fail("Should have thrown " + shouldThrowAnnotation.value());
- } catch (Throwable e) {
- if (!e.getClass().equals(shouldThrowAnnotation.value())) {
- fail("Should have thrown " + shouldThrowAnnotation.value() + " but threw " + e);
- }
- for (String requiredSubstring : shouldThrowAnnotation.messages()) {
- if (!e.getMessage().contains(requiredSubstring)) {
- fail("Error message didn't contain " + requiredSubstring + ", was " + e.getMessage());
- }
- }
- // Good, test passes.
- }
- } else {
- super.runTest();
+ protected void tearDown() throws Exception {
+ mExecutorService.shutdown();
+ super.tearDown();
}
- }
/** Simple interface for testing against. */
public interface Callback {
@@ -186,14 +163,18 @@ public class LittleMockTest extends TestCase {
assertEquals(null, mFoo.anInterface());
}
- @ShouldThrow(IllegalArgumentException.class)
public void testVerify_FailsIfNotDoneOnAProxy() {
- verify("hello").contains("something");
+ try {
+ verify("hello").contains("something");
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
- @ShouldThrow(IllegalArgumentException.class)
public void testVerify_FailsIfNotCreatedByOurMockMethod() {
- verify(createNotARealMock()).add("something");
+ try {
+ verify(createNotARealMock()).add("something");
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
public void testVerify_SuccessfulVerification() {
@@ -215,22 +196,28 @@ public class LittleMockTest extends TestCase {
verify(mFoo).add("something");
}
- @ShouldThrow(AssertionError.class)
public void testVerify_MeansOnlyOnceSoShouldFailIfCalledTwice() {
mFoo.add("something");
mFoo.add("something");
- verify(mFoo).add("something");
+ try {
+ verify(mFoo).add("something");
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerify_FailedVerification_CalledWithWrongArgument() {
mFoo.add("something else");
- verify(mFoo).add("something");
+ try {
+ verify(mFoo).add("something");
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerify_FailedVerification_WasNeverCalled() {
- verify(mFoo).add("something");
+ try {
+ verify(mFoo).add("something");
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerify_TimesTwice_Succeeds() {
@@ -239,25 +226,31 @@ public class LittleMockTest extends TestCase {
verify(mFoo, LittleMock.times(2)).add("jim");
}
- @ShouldThrow(AssertionError.class)
public void testVerify_TimesTwice_ButThreeTimesFails() {
mFoo.add("jim");
mFoo.add("jim");
mFoo.add("jim");
- verify(mFoo, LittleMock.times(2)).add("jim");
+ try {
+ verify(mFoo, LittleMock.times(2)).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerify_TimesTwice_ButOnceFails() {
mFoo.add("jim");
- verify(mFoo, LittleMock.times(2)).add("jim");
+ try {
+ verify(mFoo, LittleMock.times(2)).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerify_TimesTwice_DifferentStringsFails() {
mFoo.add("jim");
mFoo.add("bob");
- verify(mFoo, LittleMock.times(2)).add("jim");
+ try {
+ verify(mFoo, LittleMock.times(2)).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerify_TimesTwice_WorksWithAnyString() {
@@ -266,18 +259,22 @@ public class LittleMockTest extends TestCase {
verify(mFoo, LittleMock.times(2)).add(anyString());
}
- @ShouldThrow(AssertionError.class)
public void testVerify_TimesTwice_FailsIfJustOnceWithAnyString() {
mFoo.add("bob");
- verify(mFoo, LittleMock.times(2)).add(anyString());
+ try {
+ verify(mFoo, LittleMock.times(2)).add(anyString());
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerify_TimesTwice_FailsIfThreeTimesWithAnyString() {
mFoo.add("bob");
mFoo.add("jim");
mFoo.add("james");
- verify(mFoo, LittleMock.times(2)).add(anyString());
+ try {
+ verify(mFoo, LittleMock.times(2)).add(anyString());
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerify_Never_Succeeds() {
@@ -285,10 +282,12 @@ public class LittleMockTest extends TestCase {
verify(mFoo, never()).anInt();
}
- @ShouldThrow(AssertionError.class)
public void testVerify_Never_FailsIfWasCalled() {
mFoo.add("jim");
- verify(mFoo, never()).add("jim");
+ try {
+ verify(mFoo, never()).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerify_Never_PassesIfArgumentsDontMatch() {
@@ -308,9 +307,11 @@ public class LittleMockTest extends TestCase {
verify(mFoo, atLeastOnce()).add("jim");
}
- @ShouldThrow(AssertionError.class)
public void testVerify_AtLeastOnce_FailsForNoCalls() {
- verify(mFoo, atLeastOnce()).add("jim");
+ try {
+ verify(mFoo, atLeastOnce()).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerify_AtLeastThreeTimes_SuceedsForThreeCalls() {
@@ -329,11 +330,13 @@ public class LittleMockTest extends TestCase {
verify(mFoo, atLeast(3)).add("jim");
}
- @ShouldThrow(AssertionError.class)
public void testVerify_AtLeastThreeTimes_FailsForTwoCalls() {
mFoo.add("jim");
mFoo.add("jim");
- verify(mFoo, atLeast(3)).add("jim");
+ try {
+ verify(mFoo, atLeast(3)).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerify_AtMostThreeTimes_SuceedsForThreeCalls() {
@@ -343,14 +346,16 @@ public class LittleMockTest extends TestCase {
verify(mFoo, atMost(3)).add("jim");
}
- @ShouldThrow(AssertionError.class)
public void testVerify_AtMostThreeTimes_FailsForFiveCalls() {
mFoo.add("jim");
mFoo.add("jim");
mFoo.add("jim");
mFoo.add("jim");
mFoo.add("jim");
- verify(mFoo, atMost(3)).add("jim");
+ try {
+ verify(mFoo, atMost(3)).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerify_AtMostThreeTimes_SucceedsForTwoCalls() {
@@ -377,20 +382,24 @@ public class LittleMockTest extends TestCase {
verify(mFoo, between(2, 4)).add("jim");
}
- @ShouldThrow(AssertionError.class)
public void testVerify_BetweenTwoAndFour_FailsForOneCall() {
mFoo.add("jim");
- verify(mFoo, between(2, 4)).add("jim");
+ try {
+ verify(mFoo, between(2, 4)).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerify_BetweenTwoAndFour_FailsForFiveCalls() {
mFoo.add("jim");
mFoo.add("jim");
mFoo.add("jim");
mFoo.add("jim");
mFoo.add("jim");
- verify(mFoo, LittleMock.between(2, 4)).add("jim");
+ try {
+ verify(mFoo, LittleMock.between(2, 4)).add("jim");
+ fail();
+ } catch (AssertionError expected) {}
}
public void testDoReturnWhen_SimpleReturn() {
@@ -416,14 +425,18 @@ public class LittleMockTest extends TestCase {
assertEquals(null, mFoo.get(2));
}
- @ShouldThrow(IllegalArgumentException.class)
public void testDoReturnWhen_CalledOnString() {
- doReturn("first").when("hello").contains("something");
+ try {
+ doReturn("first").when("hello").contains("something");
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
- @ShouldThrow(IllegalArgumentException.class)
public void testDoReturnWhen_CalledOnNonMock() {
- doReturn("first").when(createNotARealMock()).get(0);
+ try {
+ doReturn("first").when(createNotARealMock()).get(0);
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
public void testDoReturnWhen_CanAlsoBeVerified() {
@@ -469,10 +482,12 @@ public class LittleMockTest extends TestCase {
assertEquals(null, mFoo.anInterface());
}
- @ShouldThrow(RuntimeException.class)
public void testDoThrow_SimpleException() {
doThrow(new RuntimeException()).when(mFoo).aDouble();
- mFoo.aDouble();
+ try {
+ mFoo.aDouble();
+ fail();
+ } catch (RuntimeException expected) {}
}
public void testDoThrow_IfItDoesntMatchItIsntThrown() {
@@ -480,17 +495,17 @@ public class LittleMockTest extends TestCase {
mFoo.aChar();
}
- @ShouldThrow(RuntimeException.class)
public void testDoThrow_KeepsThrowingForever() {
doThrow(new RuntimeException()).when(mFoo).aDouble();
try {
mFoo.aDouble();
- fail("Should have thrown a RuntimeException");
- } catch (RuntimeException e) {
- // Expected.
- }
+ fail();
+ } catch (RuntimeException expected) {}
// This second call should also throw a RuntimeException.
- mFoo.aDouble();
+ try {
+ mFoo.aDouble();
+ fail();
+ } catch (RuntimeException expected) {}
}
public void testDoNothing() {
@@ -502,21 +517,25 @@ public class LittleMockTest extends TestCase {
verifyZeroInteractions(mFoo);
}
- @ShouldThrow(AssertionError.class)
public void testVerifyZeroInteractions_FailsIfSomethingHasHappened() {
mFoo.aBoolean();
- verifyZeroInteractions(mFoo);
+ try {
+ verifyZeroInteractions(mFoo);
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerifyZeroInteractions_HappyWithMultipleArguments() {
verifyZeroInteractions(mFoo, mBar);
}
- @ShouldThrow(AssertionError.class)
public void testVerifyZeroInteractions_ShouldFailEvenIfOtherInteractionsWereFirstVerified() {
mFoo.add("test");
verify(mFoo).add("test");
- verifyZeroInteractions(mFoo);
+ try {
+ verifyZeroInteractions(mFoo);
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerifyEq_Method() {
@@ -534,22 +553,28 @@ public class LittleMockTest extends TestCase {
verify(mBar).mixedArguments(eq(8), eq("test"));
}
- @ShouldThrow(AssertionError.class)
public void testVerifyEq_MethodFailsIfNotEqual() {
mFoo.add("bob");
- verify(mFoo).add(eq("jim"));
+ try {
+ verify(mFoo).add(eq("jim"));
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerifyEq_MethodFailsIfJustOneIsNotEqual() {
mBar.twoStrings("first", "second");
- verify(mBar).twoStrings(eq("first"), eq("third"));
+ try {
+ verify(mBar).twoStrings(eq("first"), eq("third"));
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(AssertionError.class)
public void testVerifyEq_MethodFailsIfSameParamsButInWrongOrder() {
mBar.twoStrings("first", "second");
- verify(mBar).twoStrings(eq("second"), eq("first"));
+ try {
+ verify(mBar).twoStrings(eq("second"), eq("first"));
+ fail();
+ } catch (AssertionError expected) {}
}
public void testCapture_SimpleCapture() {
@@ -622,14 +647,6 @@ public class LittleMockTest extends TestCase {
assertEquals(newList("whinny", "jessica"), mCaptureAnotherString.getAllValues());
}
- public static <T> List<T> newList(T... things) {
- ArrayList<T> list = new ArrayList<T>();
- for (T thing : things) {
- list.add(thing);
- }
- return list;
- }
-
public void testAnyString() {
doReturn("jim").when(mFoo).lookup(anyString());
assertEquals("jim", mFoo.lookup("barney"));
@@ -641,10 +658,12 @@ public class LittleMockTest extends TestCase {
verify(mFoo).takesObject(anyString());
}
- @ShouldThrow(AssertionError.class)
public void testAnyString_ObjectValue() {
mFoo.takesObject(new Object());
- verify(mFoo).takesObject(anyString());
+ try {
+ verify(mFoo).takesObject(anyString());
+ fail();
+ } catch (AssertionError expected) {}
}
public void testAnyObject() {
@@ -696,11 +715,13 @@ public class LittleMockTest extends TestCase {
verifyZeroInteractions(mFoo);
}
- @ShouldThrow(AssertionError.class)
public void testReset_VerifyFailsAfterReset() {
mFoo.aByte();
reset(mFoo);
- verify(mFoo).aByte();
+ try {
+ verify(mFoo).aByte();
+ fail();
+ } catch (AssertionError expected) {}
}
public void testCapture_BothBeforeAndAfter() {
@@ -738,7 +759,6 @@ public class LittleMockTest extends TestCase {
verify(mFoo).add("yes");
}
- @ShouldThrow(IOException.class)
public void testDoAction_CanThrowDeclaredException() throws Exception {
doAnswer(new Callable<Void>() {
@Override
@@ -746,10 +766,12 @@ public class LittleMockTest extends TestCase {
throw new IOException("Problem");
}
}).when(mFoo).exceptionThrower();
- mFoo.exceptionThrower();
+ try {
+ mFoo.exceptionThrower();
+ fail();
+ } catch (IOException expected) {}
}
- @ShouldThrow(RuntimeException.class)
public void testDoAction_CanThrowUndelcaredException() {
doAnswer(new Callable<Void>() {
@Override
@@ -757,7 +779,10 @@ public class LittleMockTest extends TestCase {
throw new RuntimeException("Problem");
}
}).when(mFoo).aBoolean();
- mFoo.aBoolean();
+ try {
+ mFoo.aBoolean();
+ fail();
+ } catch (RuntimeException expected) {}
}
public void testRunThisIsAnAliasForDoAction() {
@@ -796,10 +821,12 @@ public class LittleMockTest extends TestCase {
verifyNoMoreInteractions(mFoo, mBar);
}
- @ShouldThrow(AssertionError.class)
public void testVerifyNoMoreInteractions_FailsWhenOneActionWasNotVerified() {
mFoo.aBoolean();
- verifyNoMoreInteractions(mFoo, mBar);
+ try {
+ verifyNoMoreInteractions(mFoo, mBar);
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerifyNoMoreInteractions_SucceedsWhenAllActionsWereVerified() {
@@ -809,13 +836,15 @@ public class LittleMockTest extends TestCase {
verifyNoMoreInteractions(mFoo);
}
- @ShouldThrow(AssertionError.class)
public void testVerifyNoMoreInteractions_FailsWhenMostButNotAllActionsWereVerified() {
mFoo.get(3);
mFoo.get(20);
mFoo.aByte();
verify(mFoo, atLeastOnce()).get(anyInt());
- verifyNoMoreInteractions(mFoo);
+ try {
+ verifyNoMoreInteractions(mFoo);
+ fail();
+ } catch (AssertionError expected) {}
}
public void testVerifyNoMoreInteractions_ShouldIngoreStubbedCalls() {
@@ -824,17 +853,20 @@ public class LittleMockTest extends TestCase {
verifyNoMoreInteractions(mFoo);
}
- @ShouldThrow(IllegalArgumentException.class)
public void testMatchers_WrongNumberOfMatchersOnStubbingCausesError() {
- doReturn("hi").when(mBar).twoStrings("jim", eq("bob"));
+ try {
+ doReturn("hi").when(mBar).twoStrings("jim", eq("bob"));
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
- @ShouldThrow(IllegalArgumentException.class)
public void testMatchers_WrongNumberOfMatchersOnVerifyCausesError() {
- verify(mBar).twoStrings("jim", eq("bob"));
+ try {
+ verify(mBar).twoStrings("jim", eq("bob"));
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
- @ShouldThrow(IllegalStateException.class)
public void testCreateACaptureButDontUseItShouldFailAtNextVerify() {
// If we create a capture illegally, outside of a method call, like so:
mCaptureString.capture();
@@ -843,23 +875,29 @@ public class LittleMockTest extends TestCase {
// call on the mock object.
// Thus we should check in the verify() method that there are *no matchers* on the static
// list, as this would indicate a programming error such as the above.
- verify(mFoo, anyTimes()).aBoolean();
+ try {
+ verify(mFoo, anyTimes()).aBoolean();
+ fail();
+ } catch (IllegalStateException expected) {}
}
- @ShouldThrow(IllegalStateException.class)
public void testCreateACaptureButDontUseItShouldFailAtNextVerify_AlsoNoMoreInteractions() {
// Same result desired as in previous test.
mCaptureString.capture();
- verifyNoMoreInteractions(mFoo);
+ try {
+ verifyNoMoreInteractions(mFoo);
+ fail();
+ } catch (IllegalStateException expected) {}
}
- @ShouldThrow(IllegalStateException.class)
public void testCreateACaptureButDontUseItShouldFailAtNextVerify_AlsoZeroInteraction() {
mCaptureString.capture();
- verifyZeroInteractions(mFoo);
+ try {
+ verifyZeroInteractions(mFoo);
+ fail();
+ } catch (IllegalStateException expected) {}
}
- @ShouldThrow(IllegalStateException.class)
public void testCheckStaticVariablesMethod() {
// To help us avoid programming errors, I'm adding a method that you can call from tear down,
// which will explode if there is anything still left in your static variables at the end
@@ -867,12 +905,17 @@ public class LittleMockTest extends TestCase {
// variable (so that the next test won't fail). It should fail if we create a matcher
// be it a capture or anything else that is then not consumed.
anyInt();
- checkForProgrammingErrorsDuringTearDown();
+ try {
+ checkForProgrammingErrorsDuringTearDown();
+ fail();
+ } catch (IllegalStateException expected) {}
}
- @ShouldThrow(IllegalArgumentException.class)
public void testCantPassNullToVerifyCount() {
- verify(mFoo, null).aBoolean();
+ try {
+ verify(mFoo, null).aBoolean();
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
public void testInjectionInNestedClasses() throws Exception {
@@ -901,10 +944,12 @@ public class LittleMockTest extends TestCase {
verify(mFoo).takesObject(isA(String.class));
}
- @ShouldThrow(AssertionError.class)
public void testIsA_FailsWithSuperclass() {
mFoo.takesObject(new Object());
- verify(mFoo).takesObject(isA(String.class));
+ try {
+ verify(mFoo).takesObject(isA(String.class));
+ fail();
+ } catch (AssertionError expected) {}
}
public void testIsA_WillAcceptNull() {
@@ -918,49 +963,57 @@ public class LittleMockTest extends TestCase {
verify(mFoo).takesBar(isA(BarSubtype.class));
}
- @ShouldThrow(AssertionError.class)
public void testIsA_MatchSubtypeFailed() {
mFoo.takesBar(mBar);
- verify(mFoo).takesBar(isA(BarSubtype.class));
+ try {
+ verify(mFoo).takesBar(isA(BarSubtype.class));
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(value = AssertionError.class,
- messages = {"cannot verify call to", "boolean java.lang.Object.equals(java.lang.Object)"})
public void testVerifyEquals_ShouldFail() {
mFoo.equals(null);
- verify(mFoo).equals(null);
+ try {
+ verify(mFoo).equals(null);
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(value = AssertionError.class,
- messages = {"cannot verify call to", "int java.lang.Object.hashCode()"})
public void testVerifyHashCode_ShouldFail() {
mFoo.hashCode();
- verify(mFoo).hashCode();
+ try {
+ verify(mFoo).hashCode();
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(value = AssertionError.class,
- messages = {"cannot verify call to", "java.lang.String java.lang.Object.toString()"})
public void testVerifyToString_ShouldFail() {
mFoo.toString();
- verify(mFoo).toString();
+ try {
+ verify(mFoo).toString();
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(value = AssertionError.class,
- messages = {"cannot stub call to", "boolean java.lang.Object.equals(java.lang.Object)"})
public void testStubEquals_ShouldFail() {
- doReturn(false).when(mFoo).equals(null);
+ try {
+ doReturn(false).when(mFoo).equals(null);
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(value = AssertionError.class,
- messages = {"cannot stub call to", "int java.lang.Object.hashCode()"})
public void testStubHashCode_ShouldFail() {
- doReturn(0).when(mFoo).hashCode();
+ try {
+ doReturn(0).when(mFoo).hashCode();
+ fail();
+ } catch (AssertionError expected) {}
}
- @ShouldThrow(value = AssertionError.class,
- messages = {"cannot stub call to", "java.lang.String java.lang.Object.toString()"})
public void testStubToString_ShouldFail() {
- doReturn("party").when(mFoo).toString();
+ try {
+ doReturn("party").when(mFoo).toString();
+ fail();
+ } catch (AssertionError expected) {}
}
public void testEqualsMethod_DoesntCountAsInteraction() {
@@ -1014,7 +1067,7 @@ public class LittleMockTest extends TestCase {
+ " mFoo.aBoolean()\n"
+ " at " + singleLineStackTrace(verifyLineNumber) + "\n"
+ "\n"
- + "No method calls happened to this mock\n";
+ + "No method calls happened on this mock\n";
assertEquals(expectedMessage, e.getMessage());
}
}
@@ -1100,23 +1153,29 @@ public class LittleMockTest extends TestCase {
}
}
- @ShouldThrow(IllegalArgumentException.class)
public void testDoReturn_ThisShouldFailSinceDoubleIsNotAString() {
- doReturn("hello").when(mFoo).aDouble();
+ try {
+ doReturn("hello").when(mFoo).aDouble();
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
public void testDoReturn_ThisShouldPassSinceStringCanBeReturnedFromObjectMethod() {
doReturn("hello").when(mFoo).anObject();
}
- @ShouldThrow(IllegalArgumentException.class)
public void testDoReturn_ThisShouldFailSinceObjectCantBeReturnedFromString() {
- doReturn(new Object()).when(mFoo).aString();
+ try {
+ doReturn(new Object()).when(mFoo).aString();
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
- @ShouldThrow(IllegalArgumentException.class)
public void testDoReturn_ThisShouldFailSinceBarIsNotSubtypeOfBarSubtype() {
- doReturn(mBar).when(mFoo).aBarSubtype();
+ try {
+ doReturn(mBar).when(mFoo).aBarSubtype();
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
public void testDoReturn_ThisShouldPassSinceBarSubTypeIsABar() {
@@ -1132,10 +1191,12 @@ public class LittleMockTest extends TestCase {
// TODO(hugohudson): 7. Should fix this.
// Once we fix the previous test we won't need this one.
// I'm just demonstrating that currently this fails with NPE at use-time not at stub-time.
- @ShouldThrow(NullPointerException.class)
public void testDoReturn_ThisShouldFailBecauseNullIsNotAByte2() {
doReturn(null).when(mFoo).aByte();
- mFoo.aByte();
+ try {
+ mFoo.aByte();
+ fail();
+ } catch (NullPointerException expected) {}
}
public void testDoReturn_ThisShouldPassSinceNullIsAnObject() {
@@ -1155,30 +1216,36 @@ public class LittleMockTest extends TestCase {
// TODO(hugohudson): 7. Should fix this to give proper message.
// We could at least give a good message saying why you get failure - saying that your string
// is not a byte, and pointing to where you stubbed it.
- @ShouldThrow(ClassCastException.class)
public void testDoAnswer_ThisShouldFailSinceStringIsNotAByte2() {
doAnswer(new Callable<String>() {
@Override public String call() throws Exception { return "hi"; }
}).when(mFoo).aByte();
- mFoo.aByte();
+ try {
+ mFoo.aByte();
+ fail();
+ } catch (ClassCastException expected) {}
}
- @ShouldThrow(value = IllegalArgumentException.class,
- messages = { " (Bar) mFoo.aBar()" })
public void testDoAnswer_ShouldHaveSimpleNameOnReturnValue() {
- doReturn("hi").when(mFoo).aBar();
+ try {
+ doReturn("hi").when(mFoo).aBar();
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
- @ShouldThrow(IllegalArgumentException.class)
public void testCantCreateMockOfNullType() {
- mock(null);
+ try {
+ mock(null);
+ fail();
+ } catch (IllegalArgumentException expected) {}
}
- @ShouldThrow(value = AssertionError.class,
- messages = { "Expected exactly 1 call to:", "onClickListener.onClick(Bar)" })
public void testCreateMockWithNullFieldName() {
OnClickListener mockClickListener = mock(OnClickListener.class);
- verify(mockClickListener).onClick(null);
+ try {
+ verify(mockClickListener).onClick(null);
+ fail();
+ } catch (AssertionError expected) {}
}
public void testDoubleVerifyNoProblems() {
@@ -1191,10 +1258,185 @@ public class LittleMockTest extends TestCase {
verify(mFoo).aByte();
}
- // TODO(hugohudson): 5. Every @ShouldThrow method should be improved by adding test for the
- // content of the error message. First augment the annotation to take a String which must
- // form a substring of the getMessage() for the Exception, then check that the exceptions
- // thrown are as informative as possible.
+ public void testUnfinishedVerifyCaughtInTearDown_Issue5() {
+ verify(mFoo);
+ try {
+ checkForProgrammingErrorsDuringTearDown();
+ fail();
+ } catch (IllegalStateException expected) {}
+ }
+
+ public void testUnfinishedWhenCaughtInTearDown_Issue5() {
+ doThrow(new RuntimeException()).when(mFoo);
+ try {
+ checkForProgrammingErrorsDuringTearDown();
+ fail();
+ } catch (IllegalStateException expected) {}
+ }
+
+ public void testUnfinishedVerifyCaughtByStartingWhen_Issue5() {
+ verify(mFoo, never());
+ try {
+ doReturn(null).when(mFoo).clear();
+ fail();
+ } catch (IllegalStateException expected) {}
+ }
+
+ public void testUnfinishedWhenCaughtByStartingVerify_Issue5() {
+ doThrow(new RuntimeException()).when(mFoo);
+ try {
+ verify(mFoo).clear();
+ fail();
+ } catch (IllegalStateException expected) {}
+ }
+
+ public void testSecondUnfinishedVerifyShouldFailImmediately() throws Exception {
+ verify(mFoo);
+ try {
+ verify(mFoo);
+ fail();
+ } catch (IllegalStateException expected) {}
+ }
+
+ public void testSecondUnfinishedWhenShouldFailImmediately() throws Exception {
+ doReturn(null).when(mFoo);
+ try {
+ doReturn(null).when(mFoo);
+ fail();
+ } catch (IllegalStateException expected) {}
+ }
+
+ public void testVerifyWithTimeout_SuccessCase() throws Exception {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ invokeBarMethodAfterLatchAwait(countDownLatch);
+ doReturn(null).when(mFoo).aBar();
+ verify(mFoo, never()).aBar();
+ countDownLatch.countDown();
+ verify(mFoo, timeout(100)).aBar();
+ }
+
+ public void testVerifyWithTimeout_FailureCase() throws Exception {
+ long start = System.currentTimeMillis();
+ try {
+ verify(mFoo, timeout(10)).aBar();
+ fail();
+ } catch (AssertionError expected) {}
+ long duration = System.currentTimeMillis() - start;
+ assertTrue(duration > 5);
+ }
+
+ public void testVerifyWithTimeoutMultipleInvocations_SuccessCase() throws Exception {
+ CountDownLatch countDownLatch = new CountDownLatch(1);
+ invokeBarMethodAfterLatchAwait(countDownLatch);
+ invokeBarMethodAfterLatchAwait(countDownLatch);
+ doReturn(null).when(mFoo).aBar();
+ verify(mFoo, never()).aBar();
+ countDownLatch.countDown();
+ verify(mFoo, timeout(100).times(2)).aBar();
+ verify(mFoo, timeout(100).atLeast(2)).aBar();
+ verify(mFoo, timeout(100).between(2, 4)).aBar();
+ verify(mFoo, timeout(100).atLeastOnce()).aBar();
+ }
+
+ public void testVerifyWithTimeoutMultipleInvocations_FailureCase() throws Exception {
+ long start = System.currentTimeMillis();
+ mFoo.aBar();
+ try {
+ verify(mFoo, timeout(10).between(2, 3)).aBar();
+ fail();
+ } catch (AssertionError expected) {}
+ long duration = System.currentTimeMillis() - start;
+ assertTrue(duration > 5);
+
+ }
+
+ public void testConcurrentModificationExceptions() throws Exception {
+ // This test concurrently stubs, verifies, and uses a mock.
+ // It used to totally reproducibly throw a ConcurrentModificationException.
+ Future<?> task1 = mExecutorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ while (!Thread.currentThread().isInterrupted()) {
+ mFoo.aBar();
+ Thread.yield();
+ }
+ }
+ });
+ Future<?> task2 = mExecutorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ while (!Thread.currentThread().isInterrupted()) {
+ verify(mFoo, anyTimes()).aBar();
+ Thread.yield();
+ }
+ }
+ });
+ Thread.sleep(20);
+ task1.cancel(true);
+ task2.cancel(true);
+ try {
+ task1.get();
+ fail();
+ } catch (CancellationException expected) {}
+ try {
+ task2.get();
+ fail();
+ } catch (CancellationException expected) {}
+ }
+
+ public void testCannotVerifyFromSecondThreadAfterStubbingInFirst() throws Exception {
+ doReturn(null).when(mFoo).aBar();
+ Future<?> submit = mExecutorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ verify(mFoo, anyTimes()).aBar();
+ }
+ });
+ try {
+ submit.get();
+ fail();
+ } catch (ExecutionException expected) {
+ assertTrue(expected.getCause() instanceof IllegalStateException);
+ }
+ }
+
+ public void testCannotStubFromSecondThreadAfterVerifyingInFirst() throws Exception {
+ mExecutorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ verify(mFoo, anyTimes()).aBar();
+ }
+ }).get();
+ try {
+ doReturn(null).when(mFoo).aBar();
+ fail();
+ } catch (IllegalStateException expected) {}
+ }
+
+ public class Jim {
+ public void bob() {
+ fail();
+ }
+ }
+
+ public void testMockingConcreteClasses() throws Exception {
+ Jim mock = mock(Jim.class);
+ mock.bob();
+ }
+
+ private Future<Void> invokeBarMethodAfterLatchAwait(final CountDownLatch countDownLatch) {
+ return mExecutorService.submit(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ countDownLatch.await();
+ mFoo.aBar();
+ return null;
+ }
+ });
+ }
+
+ // TODO(hugohudson): 5. Every method that throws exceptions could be improved by adding
+ // test for the content of the error message.
// TODO(hugohudson): 5. Add InOrder class, so that we can check that the given methods on
// the given mocks happen in the right order. It will be pretty easy to do. The syntax
@@ -1258,14 +1500,8 @@ public class LittleMockTest extends TestCase {
// //then
// assertThat(goods, containBread());
- // TODO(hugohudson): 6. How about timeouts that are mentioned in Mockito docs?
- // Sounds like a good idea. Would look like this:
- // verify(mFoo, within(50).milliseconds()).get(0);
-
- // TODO(hugohudson): 6. Consider bringing back in the async code I wrote for the AndroidMock
- // framework so that you can expect to wait for the method call.
- // Although obviously we're more keen on encouraging people to write unit tests that don't
- // require async behaviour in the first place.
+ // TODO: All unfinished verify and when statements should have sensible error messages telling
+ // you where the unfinished statement comes from.
/** Returns the line number of the line following the method call. */
private int getNextLineNumber() {
@@ -1307,4 +1543,12 @@ public class LittleMockTest extends TestCase {
}
};
}
+
+ private static <T> List<T> newList(T... things) {
+ ArrayList<T> list = new ArrayList<T>();
+ for (T thing : things) {
+ list.add(thing);
+ }
+ return list;
+ }
}