Repository: mockito/mockito
Issue: Introduce BDD InOrder verification
Labels: enhancement
BDD

Follow-up to the [discussion](https://groups.google.com/forum/#!topic/mockito/wr1As1fg_-U).

[BDDMockito](http://site.mockito.org/mockito/docs/current/org/mockito/BDDMockito.html) is great, but right now it doesn't support InOrder verification. Here is my proposition:
##### Initialization and invocations:

``` java
List firstMock = mock(List.class);
List secondMock = mock(List.class);

firstMock.add("was called first");
secondMock.add("was called second");
secondMock.add("was called second");

InOrder inOrder = inOrder(firstMock, secondMock);
```
##### Current non-BDD solution:

``` java
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");
```
##### Proposition 1:

``` java
inOrder.then(firstMock).should().add("was called first");
inOrder.then(secondMock).should(times(2)).add("was called second");
```
##### Proposition 2:

``` java
then(firstMock).should(inOrder).add("was called first");
then(secondMock).should(inOrder, times(2)).add("was called second");
```

I'm open to other propositions. What do you think? 
I can proceed with PR as soon as we will agree on API.


Issue comments:
It seems like a nice idea, let's introduce ordered BDD. I'd favor proposition 2, it reads better imho.

Since we are in a beta phase, we can try and see if the API works with this proposition. Also it should probably be easier to implement.

Also sorry for this late reply

@bric3, I've implemented the second proposition. I also like it more and implementation was really easy - please see #222.


Pull request review comments:

Patch that resolved the issue:
diff --git a/src/org/mockito/BDDMockito.java b/src/org/mockito/BDDMockito.java
index d0e280c665..4ab46397d2 100644
--- a/src/org/mockito/BDDMockito.java
+++ b/src/org/mockito/BDDMockito.java
@@ -59,7 +59,19 @@
  *   then(person).should(times(2)).ride(bike);
  *   then(police).shouldHaveZeroInteractions();
  * </code></pre>
+ * <p>
+ * It is also possible to do BDD style {@link InOrder} verification:
+ * <pre class="code"><code class="java">
+ *   InOrder inOrder = inOrder(person);
+ *
+ *   person.drive(car);
+ *   person.ride(bike);
+ *   person.ride(bike);
  *
+ *   then(person).should(inOrder).drive(car);
+ *   then(person).should(inOrder, times(2)).ride(bike);
+ * </code></pre>
+ * <p>
  * One of the purposes of BDDMockito is also to show how to tailor the mocking syntax to a different programming style.
  *
  * @since 1.8.0
@@ -231,9 +243,21 @@ public static interface Then<T> {
          */
         T should(VerificationMode mode);
 
+        /**
+         * @see InOrder#verify(Object)
+         * @since 2.0
+         */
+        T should(InOrder inOrder);
+
+        /**
+         * @see InOrder#verify(Object, VerificationMode)
+         * @since 2.0
+         */
+        T should(InOrder inOrder, VerificationMode mode);
+
         /**
          * @see #verifyZeroInteractions(Object...)
-         * @since 2.0.0
+         * @since 2.0
          */
         void shouldHaveZeroInteractions();
     }
@@ -262,9 +286,25 @@ public T should(VerificationMode mode) {
             return verify(mock, mode);
         }
 
+        /**
+         * @see InOrder#verify(Object)
+         * @since 2.0
+         */
+        public T should(InOrder inOrder) {
+            return inOrder.verify(mock);
+        }
+
+        /**
+         * @see InOrder#verify(Object, VerificationMode)
+         * @since 2.0
+         */
+        public T should(InOrder inOrder, VerificationMode mode) {
+            return inOrder.verify(mock, mode);
+        }
+
         /**
          * @see #verifyZeroInteractions(Object...)
-         * @since 2.0.0
+         * @since 2.0
          */
         public void shouldHaveZeroInteractions() {
             verifyZeroInteractions(mock);


Test patch:
diff --git a/test/org/mockitousage/customization/BDDMockitoTest.java b/test/org/mockitousage/customization/BDDMockitoTest.java
index 71b50196bc..8b9324cfdd 100644
--- a/test/org/mockitousage/customization/BDDMockitoTest.java
+++ b/test/org/mockitousage/customization/BDDMockitoTest.java
@@ -5,9 +5,11 @@
 package org.mockitousage.customization;
 
 import org.junit.Test;
+import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.exceptions.misusing.NotAMockException;
 import org.mockito.exceptions.verification.NoInteractionsWanted;
+import org.mockito.exceptions.verification.VerificationInOrderFailure;
 import org.mockito.exceptions.verification.WantedButNotInvoked;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -237,6 +239,38 @@ public void shouldFailWhenMockHadUnwantedInteractions() {
         then(mock).shouldHaveZeroInteractions();
     }
 
+    @Test
+    public void shouldPassForInteractionsThatHappenedInCorrectOrder() {
+
+        InOrder inOrder = inOrder(mock);
+
+        mock.booleanObjectReturningMethod();
+        mock.arrayReturningMethod();
+
+        then(mock).should(inOrder).booleanObjectReturningMethod();
+        then(mock).should(inOrder).arrayReturningMethod();
+    }
+
+    @Test(expected = VerificationInOrderFailure.class)
+    public void shouldFailForInteractionsThatWereInWrongOrder() {
+
+        InOrder inOrder = inOrder(mock);
+
+        mock.arrayReturningMethod();
+        mock.booleanObjectReturningMethod();
+
+        then(mock).should(inOrder).booleanObjectReturningMethod();
+        then(mock).should(inOrder).arrayReturningMethod();
+    }
+
+    @Test(expected = WantedButNotInvoked.class)
+    public void shouldFailWhenCheckingOrderOfInteractionsThatDidNotHappen() {
+
+        InOrder inOrder = inOrder(mock);
+
+        then(mock).should(inOrder).booleanObjectReturningMethod();
+    }
+
     @Test
     public void shouldPassFluentBddScenario() {
 
@@ -251,16 +285,55 @@ public void shouldPassFluentBddScenario() {
         then(police).shouldHaveZeroInteractions();
     }
 
+    @Test
+    public void shouldPassFluentBddScenarioWithOrderedVerification() {
+
+        Bike bike = new Bike();
+        Car car = new Car();
+        Person person = mock(Person.class);
+        InOrder inOrder = inOrder(person);
+
+        person.drive(car);
+        person.ride(bike);
+        person.ride(bike);
+
+        then(person).should(inOrder).drive(car);
+        then(person).should(inOrder, times(2)).ride(bike);
+    }
+
+    @Test
+    public void shouldPassFluentBddScenarioWithOrderedVerificationForTwoMocks() {
+
+        Car car = new Car();
+        Person person = mock(Person.class);
+        Police police = mock(Police.class);
+        InOrder inOrder = inOrder(person, police);
+
+        person.drive(car);
+        person.drive(car);
+        police.chase(car);
+
+        then(person).should(inOrder, times(2)).drive(car);
+        then(police).should(inOrder).chase(car);
+    }
+
     static class Person {
 
         void ride(Bike bike) {}
+
+        void drive(Car car) {}
     }
 
     static class Bike {
 
     }
 
+    static class Car {
+
+    }
+
     static class Police {
 
+        void chase(Car car) {}
     }
 }