Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito: Verify Mock (with "RETURNS_DEEP_STUBS") Returns More Calls Than Expected

Tags:

Looking at the code below, I only expect the call to getSand() to happen once, but the test is failing with four calls to it. Where are these calls happening? I want to write a test to insure that only one call is made to getSand().

Source

import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner;  import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when;  @RunWith(MockitoJUnitRunner.class) public class DeepSandTest {      @Mock(answer = Answers.RETURNS_DEEP_STUBS)     SandBox mockSandBox;      @Test     public void should(){         when(mockSandBox.getSand().doA()).thenReturn(1);         when(mockSandBox.getSand().doB()).thenReturn(1);         when(mockSandBox.getSand().doC()).thenReturn(1);          DeepSand deepSand = new DeepSand(mockSandBox);         deepSand.getTipple();          verify(mockSandBox, times(1)).getSand();     }      public class DeepSand{          private SandBox sandBox;          public DeepSand(SandBox sandBox) {             this.sandBox = sandBox;         }          public void getTipple(){             Sand sand = sandBox.getSand();             sand.doA();             sand.doB();             sand.doC();         }     }      public interface SandBox{         public Sand getSand();     }      public interface Sand{         public Integer doA();         public Integer doB();         public Integer doC();     } } 

Output

org.mockito.exceptions.verification.TooManyActualInvocations:  mockSandBox.getSand(); Wanted 1 time: -> at DeepSandTest.should(DeepSandTest.java:26) But was 4 times. Undesired invocation: -> at DeepSandTest.should(DeepSandTest.java:20) 

Details Java 1.6, JUnit 4.11, Mockito 1.9.5

Lessons Learned

If you think of deep stubs as a tree of mock objects, then you should only verify the leaves ("last mock in the chain") because the nodes are included in the call chain needed to setup the behavior of the leaves. To phrase this another way, the nodes are called during the setup of the leaves.

like image 464
Mike Rylander Avatar asked Nov 13 '13 20:11

Mike Rylander


1 Answers

It's counting your setup as invocations since deeps stubs is not supported in the verification API, and complains on the second call which is:

when(mockSandBox.getSand().doB()).thenReturn(1); 

I would skip using RETURNS_DEEP_STUBS and just use another mock:

... @Mock SandBox mockSandBox;  @Mock Sand sand;  @Test public void should(){     when(mockSandBox.getSand()).thenReturn(sand);     when(sand.doA()).thenReturn(1);     when(sand.doB()).thenReturn(1);     when(sand.doC()).thenReturn(1); ... 
like image 174
crunchdog Avatar answered Sep 28 '22 04:09

crunchdog