ssacher-tgm / mockito

Automatically exported from code.google.com/p/mockito
0 stars 0 forks source link

why atLeast() is greedy in InOrder mode? #168

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
Run this test sample:
 @Test
 public void testInOrder() {
     List mock = Mockito.mock(List.class);
     mock.add("Foo");
     mock.add("Bar");
     mock.add("Foo");

     InOrder order = Mockito.inOrder(mock);
     order.verify(mock, Mockito.atLeast(1)).add("Foo");
     order.verify(mock, Mockito.atLeast(1)).add("Bar");
     order.verify(mock, Mockito.atLeast(1)).add("Foo");
 }
What is the expected output? What do you see instead?
I expect the test to pass, I see a verification failure

What version of the product are you using? On what operating system?
Mockito 1.8, Linux

Original issue reported on code.google.com by kristofer.karlsson@gmail.com on 7 Feb 2010 at 5:12

GoogleCodeExporter commented 8 years ago
Hey,

Here's how you can fix it:

     order.verify(mock).add("Foo");
     order.verify(mock, Mockito.atLeast(1)).add("Bar");
     order.verify(mock, Mockito.atLeast(1)).add("Foo");

The reason your case fails is because atLeast() with InOrder mode is veeeeery 
tricky.
To accommodate some edge cases atLeast() matches 'eagerly', meaning single 
inOrder
will mark both interactions (#1, #3)... Hopefully it makes sense... sorry I 
don't
have more time to get into details :)

Original comment by szcze...@gmail.com on 7 Feb 2010 at 6:26

GoogleCodeExporter commented 8 years ago
Yes, I fully understand why it happens (atLeast is greedy).
It is my opinion that it shouldn't be greedy.

In which usecases is it necessary for it to be greedy?

Original comment by kristofer.karlsson@gmail.com on 7 Feb 2010 at 8:12

GoogleCodeExporter commented 8 years ago
I tried to recall why but I don't remember. I have strong feeling that there 
was a
reason for making atLest() greedy because I had to rewrite this part early in 
Mockito.

You can try to fix atLeast() to non-greedy and see what the tests say.

Original comment by szcze...@gmail.com on 10 Feb 2010 at 1:16

GoogleCodeExporter commented 8 years ago

Original comment by szcze...@gmail.com on 14 Feb 2010 at 9:55

GoogleCodeExporter commented 8 years ago
Explained why the Mockito is greedy:
http://code.google.com/p/mockito/wiki/GreedyAlgorithmOfVerficationInOrder

Original comment by szcze...@gmail.com on 11 Mar 2010 at 10:47

GoogleCodeExporter commented 8 years ago
Thanks for taking the time to write an explanation for the choice of greedy
behaviour, but I still don't understand the examples.
Why are the last two examplex contradictory?

Also, I tried running the example and I couldn't get this to fail, as the 
example showed:

    @Test
    public void simpleTest() {

        List mock = Mockito.mock(List.class);
        mock.add("A");
        mock.add("B");
        mock.add("A");
        mock.add("A");
        mock.add("B");

        InOrder inOrder = Mockito.inOrder(mock);
        //fails:
        inOrder.verify(mock, atLeast(2)).add("A");
        inOrder.verify(mock, atLeast(1)).add("B");
    }

Original comment by kristofer.karlsson@gmail.com on 11 Mar 2010 at 10:59

GoogleCodeExporter commented 8 years ago
Having read the explanation, this still does not make sense, it only explains 
why times() is greedy (because Mockito want to make sure the number of 
invocations is exact), but it does not explain why atLeast is greedy, and I 
think it shouldn't be.
Going back to the example:

 @Test
 public void testDoSomethingInOrder() {
     List mock = Mockito.mock(List.class);
     doSomething(mock); // adds an unspecified number of A's and B's...
     // ... but I do want to specify that there is an interleaving of A's and B's...
     // ... and this is the only way to verify it, only this always fails
     InOrder order = Mockito.inOrder(mock);
     order.verify(mock, atLeast(1)).add("A");
     order.verify(mock, atLeast(1)).add("B"); // always fails for times(1) as well
     order.verify(mock, atLeast(1)).add("A");
 }

Original comment by ron.pres...@gmail.com on 19 Jan 2011 at 6:41

GoogleCodeExporter commented 8 years ago
>it does not explain why atLeast is greedy

I agree. Let's say we want it to be consistent with the other parts of API :) 
If you don't like atLeast(x) being greedy - take stab at implementation.

@Kristofer - sorry I didn't see your earlier comment. Thanks for pointing out 
mistakes in the example - I fixed it. As per your question:

>Why are the last two examplex contradictory?

They aren't. Only times(x) demonstrate contradiction.

Original comment by szcze...@gmail.com on 20 Jan 2011 at 8:24