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     @Test
shouldBeAbleToMockObjectBecauseWhyNot()44     public void shouldBeAbleToMockObjectBecauseWhyNot() {
45         spy(new Object());
46     }
47 
48     @Test
shouldStub()49     public void shouldStub() {
50         spy.add("one");
51         when(spy.get(0))
52             .thenReturn("1")
53             .thenReturn("1 again");
54 
55         assertEquals("1", spy.get(0));
56         assertEquals("1 again", spy.get(0));
57         assertEquals("one", spy.iterator().next());
58 
59         assertEquals(1, spy.size());
60     }
61 
62     @Test
shouldAllowOverridingStubs()63     public void shouldAllowOverridingStubs() {
64         when(spy.contains(anyObject())).thenReturn(true);
65         when(spy.contains("foo")).thenReturn(false);
66 
67         assertTrue(spy.contains("bar"));
68         assertFalse(spy.contains("foo"));
69     }
70 
71     @Test
shouldStubVoid()72     public void shouldStubVoid() {
73         doNothing()
74         .doThrow(new RuntimeException())
75         .when(spy)
76         .clear();
77 
78         spy.add("one");
79         spy.clear();
80         try {
81             spy.clear();
82             fail();
83         } catch (RuntimeException e) {}
84 
85         assertEquals(1, spy.size());
86     }
87 
88     @Test
shouldStubWithDoReturnAndVerify()89     public void shouldStubWithDoReturnAndVerify() {
90         doReturn("foo")
91         .doReturn("bar")
92         .when(spy).get(0);
93 
94         assertEquals("foo", spy.get(0));
95         assertEquals("bar", spy.get(0));
96 
97         verify(spy, times(2)).get(0);
98         verifyNoMoreInteractions(spy);
99     }
100 
101     @Test
shouldVerifyInOrder()102     public void shouldVerifyInOrder() {
103         spy.add("one");
104         spy.add("two");
105 
106         InOrder inOrder = inOrder(spy);
107         inOrder.verify(spy).add("one");
108         inOrder.verify(spy).add("two");
109 
110         verifyNoMoreInteractions(spy);
111     }
112 
113     @Test
shouldVerifyInOrderAndFail()114     public void shouldVerifyInOrderAndFail() {
115         spy.add("one");
116         spy.add("two");
117 
118         InOrder inOrder = inOrder(spy);
119         inOrder.verify(spy).add("two");
120         try {
121             inOrder.verify(spy).add("one");
122             fail();
123         } catch (VerificationInOrderFailure f) {}
124     }
125 
126     @Test
shouldVerifyNumberOfTimes()127     public void shouldVerifyNumberOfTimes() {
128         spy.add("one");
129         spy.add("one");
130 
131         verify(spy, times(2)).add("one");
132         verifyNoMoreInteractions(spy);
133     }
134 
135     @Test
shouldVerifyNumberOfTimesAndFail()136     public void shouldVerifyNumberOfTimesAndFail() {
137         spy.add("one");
138         spy.add("one");
139 
140         try {
141             verify(spy, times(3)).add("one");
142             fail();
143         } catch (TooLittleActualInvocations e) {}
144     }
145 
146     @Test
shouldVerifyNoMoreInteractionsAndFail()147     public void shouldVerifyNoMoreInteractionsAndFail() {
148         spy.add("one");
149         spy.add("two");
150 
151         verify(spy).add("one");
152         try {
153             verifyNoMoreInteractions(spy);
154             fail();
155         } catch (NoInteractionsWanted e) {}
156     }
157 
158     @Test
shouldToString()159     public void shouldToString() {
160         spy.add("foo");
161         assertEquals("[foo]" , spy.toString());
162     }
163 
164     interface Foo {
print()165         String print();
166     }
167 
168     @Test
shouldAllowSpyingAnonymousClasses()169     public void shouldAllowSpyingAnonymousClasses() {
170         //when
171         Foo spy = spy(new Foo() {
172             public String print() {
173                 return "foo";
174             }
175         });
176 
177         //then
178         assertEquals("foo", spy.print());
179     }
180 
181     @Test
shouldSayNiceMessageWhenSpyingOnPrivateClass()182     public void shouldSayNiceMessageWhenSpyingOnPrivateClass() throws Exception {
183         List<String> real = Arrays.asList("first", "second");
184         try {
185             List<String> spy = spy(real);
186             assumeTrue("Using inline mocks, it is possible to spy on private types", spy.getClass() != real.getClass());
187             fail();
188         } catch (MockitoException e) {
189             assertThat(e).hasMessageContaining("Most likely it is due to mocking a private class that is not visible to Mockito");
190         }
191     }
192 }
193