/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import org.junit.*; import org.junit.rules.*; import mockit.internal.*; import org.hamcrest.*; @SuppressWarnings("UnusedDeclaration") public final class VerificationsWithPartialOrderingTest { @Rule public final ExpectedException thrown = ExpectedException.none(); public static class Dependency { public void setSomething(int value) {} public void setSomethingElse(String value) {} public void editABunchMoreStuff() {} public void notifyBeforeSave() {} public void prepare() {} public void save() {} } @Mocked Dependency mock; void exerciseCodeUnderTest() { mock.prepare(); mock.setSomething(123); mock.setSomethingElse("anotherValue"); mock.editABunchMoreStuff(); mock.notifyBeforeSave(); mock.save(); } @Test public void verifyFirstCallOnly() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); }}; } @Test public void verifyFirstCallWhichWasRecordedWithAConstraint() { new Expectations() {{ mock.prepare(); times = 1; }}; exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); mock.setSomething(anyInt); unverifiedInvocations(); }}; } @Test public void verifyFirstCall_outOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.setSomething(123); mock.prepare(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); }}; } @Test public void verifyLastCallOnly() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ unverifiedInvocations(); mock.save(); }}; } @Test public void verifyLastTwoCalls() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ unverifiedInvocations(); mock.notifyBeforeSave(); mock.save(); }}; } @Test public void verifyLastCallWhenOutOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.setSomething(123); mock.save(); mock.editABunchMoreStuff(); new VerificationsInOrder() {{ unverifiedInvocations(); mock.save(); }}; } @Test public void verifyLastTwoCallsWhenOutOfOrder() { thrown.expect(MissingInvocation.class); mock.setSomething(123); mock.save(); mock.notifyBeforeSave(); new VerificationsInOrder() {{ unverifiedInvocations(); mock.notifyBeforeSave(); mock.save(); }}; } @Test public void verifyFirstAndLastCallsWhenOutOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.prepare(); mock.setSomething(123); mock.setSomethingElse("anotherValue"); mock.notifyBeforeSave(); mock.editABunchMoreStuff(); mock.save(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.notifyBeforeSave(); mock.save(); }}; } @Test public void verifyFirstCallThenOthersInAnyOrder() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); }}; new Verifications() {{ mock.setSomethingElse("anotherValue"); mock.setSomething(123); }}; } @Test public void verifySomeCallsInAnyOrderThenFirstCall_outOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.setSomething(123); mock.editABunchMoreStuff(); mock.prepare(); new Verifications() {{ mock.setSomething(123); }}; new VerificationsInOrder() {{ mock.prepare(); times = 1; unverifiedInvocations(); }}; } @Test public void verifySomeCallsInAnyOrderThenLastCall() { exerciseCodeUnderTest(); new Verifications() {{ mock.setSomethingElse("anotherValue"); mock.setSomething(123); }}; new VerificationsInOrder() {{ unverifiedInvocations(); mock.save(); times = 1; }}; } @Test public void attemptToUseOrderedVerificationsAsAlreadyVerified() { thrown.expect(IllegalArgumentException.class); mock.prepare(); mock.editABunchMoreStuff(); mock.save(); final Verifications verified = new VerificationsInOrder() {{ mock.prepare(); mock.editABunchMoreStuff(); }}; new VerificationsInOrder() {{ verifiedInvocations(verified); }}; } @Test public void verifyThatSomeCallsInAnyRelativeOrderOccurBeforeAllOthers() { // These can occur in any order, but before any others: mock.prepare(); mock.setSomethingElse("anotherValue"); mock.setSomethingElse(null); // Not verified, but must occur after all others: mock.setSomething(123); mock.save(); final Verifications initialGroupOfInvocations = new Verifications() {{ mock.prepare(); mock.setSomethingElse(anyString); }}; new VerificationsInOrder() {{ verifiedInvocations(initialGroupOfInvocations); unverifiedInvocations(); }}; } @Test public void verifyThatSomeCallsInAnyRelativeOrderOccurBeforeAllOthers_outOfOrder() { thrown.expect(UnexpectedInvocation.class); // Not verified, but should occur *after* the verified invocations: mock.save(); // Verified: mock.prepare(); mock.editABunchMoreStuff(); // Not verified: mock.setSomething(123); final Verifications initialGroupOfInvocations = new Verifications() {{ mock.prepare(); mock.editABunchMoreStuff(); }}; new VerificationsInOrder() {{ verifiedInvocations(initialGroupOfInvocations); unverifiedInvocations(); }}; } @Test public void verifyThatSomeCallsInAnyRelativeOrderOccurAfterAllOthers() { // Not verified: mock.prepare(); mock.setSomething(123); // Verified in any order: mock.setSomethingElse("anotherValue"); mock.save(); mock.setSomethingElse(null); final Verifications finalGroupOfInvocations = new Verifications() {{ mock.setSomethingElse(anyString); mock.save(); }}; new VerificationsInOrder() {{ unverifiedInvocations(); verifiedInvocations(finalGroupOfInvocations); }}; } @Test public void verifyThatSomeCallsInAnyRelativeOrderOccurAfterAllOthers_outOfOrder() { thrown.expect(UnexpectedInvocation.class); // Not verified: mock.prepare(); // Verified in any order: mock.setSomethingElse("anotherValue"); mock.setSomethingElse(null); mock.save(); // Not verified, but should occur *before* the verified ones: mock.setSomething(123); final Verifications finalGroupOfInvocations = new Verifications() {{ mock.setSomethingElse(anyString); mock.save(); }}; new VerificationsInOrder() {{ unverifiedInvocations(); verifiedInvocations(finalGroupOfInvocations); }}; } @Test public void verifyThatUnorderedGroupOfCallsOccursAfterOneOtherCall_outOfOrder() { thrown.expect(UnexpectedInvocation.class); thrown.expectCause(new CustomTypeSafeMatcher<Throwable>("starting with \"Unexpected invocation \"") { @Override protected boolean matchesSafely(Throwable cause) { return cause.toString().startsWith("Unexpected invocation "); } }); mock.setSomething(123); mock.editABunchMoreStuff(); mock.prepare(); final Verifications v = new Verifications() {{ mock.editABunchMoreStuff(); mock.setSomething(anyInt); }}; new VerificationsInOrder() {{ mock.prepare(); verifiedInvocations(v); }}; } @Test public void verifyThatAnOrderedGroupOfCallsOccursBetweenTwoOtherGroupsOfCalls(@Mocked final Runnable aCallback) { // First group, happening before everything else in any order: mock.prepare(); aCallback.run(); // Verified intermediate invocations, occurring in this order: mock.setSomething(123); mock.setSomethingElse("anotherValue"); mock.setSomethingElse(null); mock.editABunchMoreStuff(); // Second group, happening after everything else in any order: mock.notifyBeforeSave(); mock.save(); final Verifications before = new Verifications() {{ aCallback.run(); mock.prepare(); }}; final Verifications after = new Verifications() {{ mock.save(); mock.notifyBeforeSave(); }}; new VerificationsInOrder() {{ verifiedInvocations(before); mock.setSomething(anyInt); mock.setSomethingElse(anyString); times = 2; mock.editABunchMoreStuff(); verifiedInvocations(after); }}; } @Test public void verifyThatAnOrderedGroupOfCallsOccursBetweenTwoOtherGroupsOfCalls_outOfOrder( @Mocked final Runnable aCallback) { thrown.expect(UnexpectedInvocation.class); // First verified group, happening before everything else in any order: mock.prepare(); aCallback.run(); // Verified intermediate invocations, occurring in this order: mock.setSomething(123); mock.setSomethingElse("anotherValue"); mock.setSomethingElse(null); mock.editABunchMoreStuff(); // Unexpected (and unverified): mock.setSomethingElse(""); // Second verified group, happening after everything else in any order: mock.notifyBeforeSave(); mock.save(); final Verifications before = new Verifications() {{ aCallback.run(); mock.prepare(); }}; final Verifications after = new Verifications() {{ mock.save(); mock.notifyBeforeSave(); }}; new VerificationsInOrder() {{ verifiedInvocations(before); mock.setSomething(anyInt); mock.setSomethingElse(anyString); times = 2; mock.editABunchMoreStuff(); verifiedInvocations(after); }}; } @Test public void verifyThatAnUnverifiedGroupOfCallsOccursBetweenTwoOtherGroupsOfCalls(@Mocked final Runnable aCallback) { // Initial invocation: mock.prepare(); // First group, happening before everything else in any order: mock.setSomething(123); mock.setSomething(-56); // Intermediate invocations, occurring in any order: mock.setSomethingElse("anotherValue"); mock.editABunchMoreStuff(); mock.setSomethingElse(null); // Second group, happening after everything else in any order: aCallback.run(); mock.save(); final Verifications before = new Verifications() {{ mock.setSomething(anyInt); }}; final Verifications after = new Verifications() {{ mock.save(); aCallback.run(); }}; new VerificationsInOrder() {{ mock.prepare(); verifiedInvocations(before); unverifiedInvocations(); verifiedInvocations(after); }}; } @Test public void verifyThatAnUnverifiedGroupOfCallsOccursBetweenTwoOtherGroupsOfCalls_outOfOrder( @Mocked final Runnable aCallback) { thrown.expect(UnexpectedInvocation.class); // First group, happening before everything else in any order: mock.setSomething(123); mock.setSomething(-56); // Unverified intermediate invocations, occurring in any order: mock.setSomethingElse("anotherValue"); // Second group, happening after everything else in any order: aCallback.run(); mock.editABunchMoreStuff(); // out of place mock.save(); final Verifications before = new Verifications() {{ mock.setSomething(anyInt); times = 2; }}; final Verifications after = new Verifications() {{ aCallback.run(); mock.save(); }}; new VerificationsInOrder() {{ verifiedInvocations(before); unverifiedInvocations(); verifiedInvocations(after); }}; } @Test public void verifyThatOneGroupOfInvocationsOccursBeforeAnother() { mock.prepare(); mock.save(); final Verifications first = new Verifications() {{ mock.prepare(); }}; final Verifications last = new Verifications() {{ mock.save(); }}; new VerificationsInOrder() {{ verifiedInvocations(first); unverifiedInvocations(); verifiedInvocations(last); }}; } @Test public void verifyThatOneGroupOfInvocationsOccursBeforeAnother_outOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.save(); mock.prepare(); final Verifications first = new Verifications() {{ mock.prepare(); }}; final Verifications last = new Verifications() {{ mock.save(); }}; new VerificationsInOrder() {{ verifiedInvocations(first); verifiedInvocations(last); }}; } @Test public void verifyThatOneGroupOccursBeforeAnotherAllowingUnverifiedInvocationsInBetween_outOfOrder() { thrown.expect(UnexpectedInvocation.class); thrown.expectMessage("Invocation occurred unexpectedly before another "); mock.save(); mock.prepare(); final Verifications first = new Verifications() {{ mock.prepare(); }}; final Verifications last = new Verifications() {{ mock.save(); }}; new VerificationsInOrder() {{ verifiedInvocations(first); unverifiedInvocations(); verifiedInvocations(last); }}; } @Test public void verifyFirstAndLastCalls() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.notifyBeforeSave(); mock.save(); }}; } @Test public void verifyFirstAndLastCallsWithFirstOutOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.editABunchMoreStuff(); mock.prepare(); mock.save(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.save(); }}; } @Test public void verifyFirstAndLastInvocationsWithSomeInvocationsInBetweenImplicitlyVerified() { thrown.expect(UnexpectedInvocation.class); new Expectations() {{ mock.setSomething(anyInt); }}; exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); // For the test to pass, a call to unverifiedInvocations() should be // inserted here, even if verification occurred implicitly. mock.setSomethingElse(anyString); unverifiedInvocations(); mock.save(); }}; } @Test public void verifyFirstAndLastCallsWithLastOutOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.prepare(); mock.editABunchMoreStuff(); mock.save(); mock.notifyBeforeSave(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.save(); }}; } @Test public void verifyFirstAndLastCallsWithOthersInBetweenInAnyOrderWithYetAnotherCallAnywhere() { mock.prepare(); // first call mock.editABunchMoreStuff(); mock.notifyBeforeSave(); mock.save(); // last call mock.setSomething(3); // could occur anywhere new Verifications() {{ mock.setSomething(anyInt); }}; new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.save(); }}; } @Test public void verifyTwoOrderedCallsAfterVerifyingDifferentCallsToSameMethodInAnyOrder() { mock.setSomething(1); mock.prepare(); mock.setSomething(2); mock.save(); mock.setSomething(3); new Verifications() {{ mock.setSomething(anyInt); times = 3; }}; new VerificationsInOrder() {{ mock.prepare(); mock.save(); }}; } @Test public void verifyFirstAndLastCallsWithOthersInBetweenInAnyOrder() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.notifyBeforeSave(); mock.save(); }}; new Verifications() {{ mock.setSomething(123); mock.setSomethingElse("anotherValue"); }}; } @Test public void verifyFirstAndLastCallsWithOthersInBetweenInAnyOrderWhenOutOfOrder() { thrown.expect(UnexpectedInvocation.class); mock.prepare(); mock.setSomething(123); mock.setSomethingElse("anotherValue"); mock.notifyBeforeSave(); mock.editABunchMoreStuff(); mock.save(); new Verifications() {{ mock.setSomethingElse("anotherValue"); mock.setSomething(anyInt); }}; new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.notifyBeforeSave(); mock.save(); }}; } @Test public void verifyConsecutiveInvocations() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.setSomething(123); mock.setSomethingElse("anotherValue"); unverifiedInvocations(); mock.save(); }}; } @Test public void verifyConsecutiveInvocationsWhenNotConsecutive() { thrown.expect(UnexpectedInvocation.class); mock.prepare(); mock.setSomething(123); mock.setSomethingElse("anotherValue"); mock.setSomething(45); mock.save(); new VerificationsInOrder() {{ unverifiedInvocations(); mock.setSomething(123); mock.setSomething(45); unverifiedInvocations(); }}; } @Test public void verifyConsecutiveInvocationsInTwoSequences() { exerciseCodeUnderTest(); new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); mock.setSomething(123); mock.setSomethingElse(anyString); unverifiedInvocations(); mock.notifyBeforeSave(); unverifiedInvocations(); }}; } @Test public void accountForUnverifiedInvocationsWithAllAlreadyVerifiedInAPreviousBlock() { mock.prepare(); mock.setSomething(123); mock.setSomething(45); mock.setSomethingElse("anotherValue"); mock.notifyBeforeSave(); mock.save(); new Verifications() {{ mock.setSomething(anyInt); mock.setSomethingElse(anyString); mock.notifyBeforeSave(); maxTimes = 1; }}; new VerificationsInOrder() {{ mock.prepare(); unverifiedInvocations(); // nothing was left unverified mock.save(); }}; } }