1 /*
2  * Copyright (c) 2007 Mockito contributors
3  * This program is made available under the terms of the MIT License.
4  */
5 
6 package org.mockitousage.spies;
7 
8 import org.junit.Test;
9 import org.mockito.InOrder;
10 import org.mockito.Mockito;
11 import org.mockito.exceptions.base.MockitoException;
12 import org.mockito.exceptions.verification.NoInteractionsWanted;
13 import org.mockito.exceptions.verification.TooLittleActualInvocations;
14 import org.mockito.exceptions.verification.VerificationInOrderFailure;
15 import org.mockitoutil.TestBase;
16 
17 import java.util.Arrays;
18 import java.util.LinkedList;
19 import java.util.List;
20 
21 import static org.junit.Assert.*;
22 import static org.assertj.core.api.Assertions.assertThat;
23 import static org.junit.Assume.assumeTrue;
24 import static org.mockito.Mockito.*;
25 
26 public class SpyingOnRealObjectsTest extends TestBase {
27 
28     List<String> list = new LinkedList<String>();
29     List<String> spy = Mockito.spy(list);
30 
31     @Test
shouldVerify()32     public void shouldVerify() {
33         spy.add("one");
34         spy.add("two");
35 
36         assertEquals("one", spy.get(0));
37         assertEquals("two", spy.get(1));
38 
39         verify(spy).add("one");
40         verify(spy).add("two");
41     }
42 
43     @SuppressWarnings({"CheckReturnValue", "MockitoUsage"})
44     @Test
shouldBeAbleToMockObjectBecauseWhyNot()45     public void shouldBeAbleToMockObjectBecauseWhyNot() {
46         spy(new Object());
47     }
48 
49     @Test
shouldStub()50     public void shouldStub() {
51         spy.add("one");
52         when(spy.get(0))
53             .thenReturn("1")
54             .thenReturn("1 again");
55 
56         assertEquals("1", spy.get(0));
57         assertEquals("1 again", spy.get(0));
58         assertEquals("one", spy.iterator().next());
59 
60         assertEquals(1, spy.size());
61     }
62 
63     @Test
shouldAllowOverridingStubs()64     public void shouldAllowOverridingStubs() {
65         when(spy.contains(anyObject())).thenReturn(true);
66         when(spy.contains("foo")).thenReturn(false);
67 
68         assertTrue(spy.contains("bar"));
69         assertFalse(spy.contains("foo"));
70     }
71 
72     @Test
shouldStubVoid()73     public void shouldStubVoid() {
74         doNothing()
75         .doThrow(new RuntimeException())
76         .when(spy)
77         .clear();
78 
79         spy.add("one");
80         spy.clear();
81         try {
82             spy.clear();
83             fail();
84         } catch (RuntimeException e) {}
85 
86         assertEquals(1, spy.size());
87     }
88 
89     @Test
shouldStubWithDoReturnAndVerify()90     public void shouldStubWithDoReturnAndVerify() {
91         doReturn("foo")
92         .doReturn("bar")
93         .when(spy).get(0);
94 
95         assertEquals("foo", spy.get(0));
96         assertEquals("bar", spy.get(0));
97 
98         verify(spy, times(2)).get(0);
99         verifyNoMoreInteractions(spy);
100     }
101 
102     @Test
shouldVerifyInOrder()103     public void shouldVerifyInOrder() {
104         spy.add("one");
105         spy.add("two");
106 
107         InOrder inOrder = inOrder(spy);
108         inOrder.verify(spy).add("one");
109         inOrder.verify(spy).add("two");
110 
111         verifyNoMoreInteractions(spy);
112     }
113 
114     @Test
shouldVerifyInOrderAndFail()115     public void shouldVerifyInOrderAndFail() {
116         spy.add("one");
117         spy.add("two");
118 
119         InOrder inOrder = inOrder(spy);
120         inOrder.verify(spy).add("two");
121         try {
122             inOrder.verify(spy).add("one");
123             fail();
124         } catch (VerificationInOrderFailure f) {}
125     }
126 
127     @Test
shouldVerifyNumberOfTimes()128     public void shouldVerifyNumberOfTimes() {
129         spy.add("one");
130         spy.add("one");
131 
132         verify(spy, times(2)).add("one");
133         verifyNoMoreInteractions(spy);
134     }
135 
136     @Test
shouldVerifyNumberOfTimesAndFail()137     public void shouldVerifyNumberOfTimesAndFail() {
138         spy.add("one");
139         spy.add("one");
140 
141         try {
142             verify(spy, times(3)).add("one");
143             fail();
144         } catch (TooLittleActualInvocations e) {}
145     }
146 
147     @Test
shouldVerifyNoMoreInteractionsAndFail()148     public void shouldVerifyNoMoreInteractionsAndFail() {
149         spy.add("one");
150         spy.add("two");
151 
152         verify(spy).add("one");
153         try {
154             verifyNoMoreInteractions(spy);
155             fail();
156         } catch (NoInteractionsWanted e) {}
157     }
158 
159     @Test
shouldToString()160     public void shouldToString() {
161         spy.add("foo");
162         assertEquals("[foo]" , spy.toString());
163     }
164 
165     interface Foo {
print()166         String print();
167     }
168 
169     @Test
shouldAllowSpyingAnonymousClasses()170     public void shouldAllowSpyingAnonymousClasses() {
171         //when
172         Foo spy = spy(new Foo() {
173             public String print() {
174                 return "foo";
175             }
176         });
177 
178         //then
179         assertEquals("foo", spy.print());
180     }
181 
182     @Test
shouldSayNiceMessageWhenSpyingOnPrivateClass()183     public void shouldSayNiceMessageWhenSpyingOnPrivateClass() throws Exception {
184         List<String> real = Arrays.asList("first", "second");
185         try {
186             List<String> spy = spy(real);
187             assumeTrue("Using inline mocks, it is possible to spy on private types", spy.getClass() != real.getClass());
188             fail();
189         } catch (MockitoException e) {
190             assertThat(e).hasMessageContaining("Most likely it is due to mocking a private class that is not visible to Mockito");
191         }
192     }
193 }
194