• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2007 Mockito contributors
3  * This program is made available under the terms of the MIT License.
4  */
5 package org.mockitousage.stubbing;
6 
7 import static org.assertj.core.api.Assertions.assertThat;
8 import static org.junit.Assert.assertEquals;
9 import static org.junit.Assert.assertNotNull;
10 import static org.junit.Assert.assertNull;
11 import static org.junit.Assert.assertSame;
12 import static org.junit.Assert.fail;
13 import static org.mockito.BDDMockito.given;
14 import static org.mockito.Mockito.*;
15 
16 import java.io.ByteArrayOutputStream;
17 import java.io.OutputStream;
18 import java.net.Socket;
19 import java.util.List;
20 import java.util.Locale;
21 
22 import javax.net.SocketFactory;
23 
24 import org.junit.Test;
25 import org.mockito.InOrder;
26 import org.mockito.MockSettings;
27 import org.mockito.exceptions.verification.TooManyActualInvocations;
28 import org.mockitoutil.TestBase;
29 
30 public class DeepStubbingTest extends TestBase {
31 
32     static class Person {
33         Address address;
34 
getAddress()35         public Address getAddress() {
36             return address;
37         }
38 
getAddress(String addressName)39         public Address getAddress(String addressName) {
40             return address;
41         }
42 
getFinalClass()43         public FinalClass getFinalClass() {
44             return null;
45         }
46     }
47 
48     static class Address {
49         Street street;
50 
getStreet()51         public Street getStreet() {
52             return street;
53         }
54 
getStreet(Locale locale)55         public Street getStreet(Locale locale) {
56             return street;
57         }
58     }
59 
60     static class Street {
61         String name;
62 
getName()63         public String getName() {
64             return name;
65         }
66 
getLongName()67         public String getLongName() {
68             return name;
69         }
70     }
71 
72     static final class FinalClass {}
73 
74     interface First {
getSecond()75         Second getSecond();
76 
getString()77         String getString();
78     }
79 
80     interface Second extends List<String> {}
81 
82     class BaseClassGenerics<A, B> {}
83 
84     class ReversedGenerics<A, B> extends BaseClassGenerics<A, B> {
reverse()85         ReversedGenerics<B, A> reverse() {
86             return null;
87         }
88 
finalMethod()89         A finalMethod() {
90             return null;
91         }
92     }
93 
94     class SuperOfReversedGenerics extends ReversedGenerics<String, Long> {}
95 
96     @Test
myTest()97     public void myTest() throws Exception {
98         SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
99         when(sf.createSocket(anyString(), eq(80))).thenReturn(null);
100         sf.createSocket("what", 80);
101     }
102 
103     @Test
simpleCase()104     public void simpleCase() throws Exception {
105         OutputStream out = new ByteArrayOutputStream();
106         Socket socket = mock(Socket.class);
107         when(socket.getOutputStream()).thenReturn(out);
108 
109         assertSame(out, socket.getOutputStream());
110     }
111 
112     /**
113      * Test that deep stubbing works for one intermediate level
114      */
115     @Test
oneLevelDeep()116     public void oneLevelDeep() throws Exception {
117         OutputStream out = new ByteArrayOutputStream();
118 
119         SocketFactory socketFactory = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
120         when(socketFactory.createSocket().getOutputStream()).thenReturn(out);
121 
122         assertSame(out, socketFactory.createSocket().getOutputStream());
123     }
124 
125     /**
126      * Test that stubbing of two mocks stubs don't interfere
127      */
128     @Test
interactions()129     public void interactions() throws Exception {
130         OutputStream out1 = new ByteArrayOutputStream();
131         OutputStream out2 = new ByteArrayOutputStream();
132 
133         SocketFactory sf1 = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
134         when(sf1.createSocket().getOutputStream()).thenReturn(out1);
135 
136         SocketFactory sf2 = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
137         when(sf2.createSocket().getOutputStream()).thenReturn(out2);
138 
139         assertSame(out1, sf1.createSocket().getOutputStream());
140         assertSame(out2, sf2.createSocket().getOutputStream());
141     }
142 
143     /**
144      * Test that stubbing of methods of different arguments don't interfere
145      */
146     @Test
withArguments()147     public void withArguments() throws Exception {
148         OutputStream out1 = new ByteArrayOutputStream();
149         OutputStream out2 = new ByteArrayOutputStream();
150         OutputStream out3 = new ByteArrayOutputStream();
151 
152         SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
153         when(sf.createSocket().getOutputStream()).thenReturn(out1);
154         when(sf.createSocket("google.com", 80).getOutputStream()).thenReturn(out2);
155         when(sf.createSocket("stackoverflow.com", 80).getOutputStream()).thenReturn(out3);
156 
157         assertSame(out1, sf.createSocket().getOutputStream());
158         assertSame(out2, sf.createSocket("google.com", 80).getOutputStream());
159         assertSame(out3, sf.createSocket("stackoverflow.com", 80).getOutputStream());
160     }
161 
162     /**
163      * Test that deep stubbing work with argument patterns
164      */
165     @Test
withAnyPatternArguments()166     public void withAnyPatternArguments() throws Exception {
167         OutputStream out = new ByteArrayOutputStream();
168 
169         // TODO: should not use javax in case it changes
170         SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
171         when(sf.createSocket(anyString(), anyInt()).getOutputStream()).thenReturn(out);
172 
173         assertSame(out, sf.createSocket("google.com", 80).getOutputStream());
174         assertSame(out, sf.createSocket("stackoverflow.com", 8080).getOutputStream());
175     }
176 
177     /**
178      * Test that deep stubbing work with argument patterns
179      */
180     @Test
withComplexPatternArguments()181     public void withComplexPatternArguments() throws Exception {
182         OutputStream out1 = new ByteArrayOutputStream();
183         OutputStream out2 = new ByteArrayOutputStream();
184 
185         SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
186         when(sf.createSocket(anyString(), eq(80)).getOutputStream()).thenReturn(out1);
187         when(sf.createSocket(anyString(), eq(8080)).getOutputStream()).thenReturn(out2);
188 
189         assertSame(out2, sf.createSocket("stackoverflow.com", 8080).getOutputStream());
190         assertSame(out1, sf.createSocket("google.com", 80).getOutputStream());
191         assertSame(out2, sf.createSocket("google.com", 8080).getOutputStream());
192         assertSame(out1, sf.createSocket("stackoverflow.com", 80).getOutputStream());
193     }
194 
195     /**
196      * Test that deep stubbing work with primitive expected values
197      */
198     @Test
withSimplePrimitive()199     public void withSimplePrimitive() throws Exception {
200         int a = 32;
201 
202         SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
203         when(sf.createSocket().getPort()).thenReturn(a);
204 
205         assertEquals(a, sf.createSocket().getPort());
206     }
207 
208     /**
209      * Test that deep stubbing work with primitive expected values with
210      * pattern method arguments
211      */
212     @Test
withPatternPrimitive()213     public void withPatternPrimitive() throws Exception {
214         int a = 12, b = 23, c = 34;
215 
216         SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
217         when(sf.createSocket(eq("stackoverflow.com"), eq(80)).getPort()).thenReturn(a);
218         when(sf.createSocket(eq("google.com"), anyInt()).getPort()).thenReturn(b);
219         when(sf.createSocket(eq("stackoverflow.com"), eq(8080)).getPort()).thenReturn(c);
220 
221         assertEquals(b, sf.createSocket("google.com", 80).getPort());
222         assertEquals(c, sf.createSocket("stackoverflow.com", 8080).getPort());
223         assertEquals(a, sf.createSocket("stackoverflow.com", 80).getPort());
224     }
225 
226     @Test
unnamed_to_string()227     public void unnamed_to_string() {
228         SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
229         assertNotNull(sf.toString());
230     }
231 
232     @Test
named_to_string()233     public void named_to_string() {
234         MockSettings settings =
235                 withSettings().name("name of mock").defaultAnswer(RETURNS_DEEP_STUBS);
236         SocketFactory sf = mock(SocketFactory.class, settings);
237         assertEquals("name of mock", sf.toString());
238     }
239 
240     Person person = mock(Person.class, RETURNS_DEEP_STUBS);
241 
242     @Test
shouldStubbingBasicallyWorkFine()243     public void shouldStubbingBasicallyWorkFine() {
244         // given
245         given(person.getAddress().getStreet().getName()).willReturn("Norymberska");
246 
247         // when
248         String street = person.getAddress().getStreet().getName();
249 
250         // then
251         assertEquals("Norymberska", street);
252     }
253 
254     @Test
shouldVerificationBasicallyWorkFine()255     public void shouldVerificationBasicallyWorkFine() {
256         // given
257         person.getAddress().getStreet().getName();
258 
259         // then
260         verify(person.getAddress().getStreet()).getName();
261     }
262 
263     @Test
verification_work_with_argument_Matchers_in_nested_calls()264     public void verification_work_with_argument_Matchers_in_nested_calls() {
265         // given
266         person.getAddress("111 Mock Lane").getStreet();
267         person.getAddress("111 Mock Lane").getStreet(Locale.ITALIAN).getName();
268 
269         // then
270         verify(person.getAddress(anyString())).getStreet();
271         verify(person.getAddress(anyString()).getStreet(Locale.CHINESE), never()).getName();
272         verify(person.getAddress(anyString()).getStreet(eq(Locale.ITALIAN))).getName();
273     }
274 
275     @Test
deep_stub_return_same_mock_instance_if_invocation_matchers_matches()276     public void deep_stub_return_same_mock_instance_if_invocation_matchers_matches() {
277         when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
278 
279         person.getAddress("the docks").getStreet().getName();
280 
281         assertSame(
282                 person.getAddress("the docks").getStreet(),
283                 person.getAddress(anyString()).getStreet());
284         assertSame(
285                 person.getAddress(anyString()).getStreet(),
286                 person.getAddress(anyString()).getStreet());
287         assertSame(
288                 person.getAddress("the docks").getStreet(),
289                 person.getAddress("the docks").getStreet());
290         assertSame(
291                 person.getAddress(anyString()).getStreet(),
292                 person.getAddress("the docks").getStreet());
293         assertSame(
294                 person.getAddress("111 Mock Lane").getStreet(),
295                 person.getAddress("the docks").getStreet());
296     }
297 
298     @Test
times_never_atLeast_atMost_verificationModes_should_work()299     public void times_never_atLeast_atMost_verificationModes_should_work() {
300         when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
301 
302         person.getAddress("the docks").getStreet().getName();
303         person.getAddress("the docks").getStreet().getName();
304         person.getAddress("the docks").getStreet().getName();
305         person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
306 
307         verify(person.getAddress("the docks").getStreet(), times(3)).getName();
308         verify(person.getAddress("the docks").getStreet(Locale.CHINESE), never()).getName();
309         verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atMostOnce()).getName();
310     }
311 
312     @Test
inOrder_only_work_on_the_very_last_mock_but_it_works()313     public void inOrder_only_work_on_the_very_last_mock_but_it_works() {
314         when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
315         when(person.getAddress(anyString()).getStreet(Locale.ITALIAN).getName()).thenReturn("deep");
316         when(person.getAddress(anyString()).getStreet(Locale.CHINESE).getName()).thenReturn("deep");
317 
318         person.getAddress("the docks").getStreet().getName();
319         person.getAddress("the docks").getStreet().getLongName();
320         person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
321         person.getAddress("the docks").getStreet(Locale.CHINESE).getName();
322 
323         InOrder inOrder =
324                 inOrder(
325                         person.getAddress("the docks").getStreet(),
326                         person.getAddress("the docks").getStreet(Locale.CHINESE),
327                         person.getAddress("the docks").getStreet(Locale.ITALIAN));
328         inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName();
329         inOrder.verify(person.getAddress("the docks").getStreet()).getLongName();
330         inOrder.verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atLeast(1))
331                 .getName();
332         inOrder.verify(person.getAddress("the docks").getStreet(Locale.CHINESE)).getName();
333     }
334 
335     @Test
verificationMode_only_work_on_the_last_returned_mock()336     public void verificationMode_only_work_on_the_last_returned_mock() {
337         // 1st invocation on Address mock (stubbing)
338         when(person.getAddress("the docks").getStreet().getName()).thenReturn("deep");
339 
340         // 2nd invocation on Address mock (real)
341         person.getAddress("the docks").getStreet().getName();
342         // 3rd invocation on Address mock (verification)
343         // (Address mock is not in verification mode)
344         verify(person.getAddress("the docks").getStreet()).getName();
345 
346         try {
347             verify(person.getAddress("the docks"), times(1)).getStreet();
348             fail();
349         } catch (TooManyActualInvocations e) {
350             assertThat(e.getMessage()).contains("Wanted 1 time").contains("But was 3 times");
351         }
352     }
353 
354     @Test
shouldFailGracefullyWhenClassIsFinal()355     public void shouldFailGracefullyWhenClassIsFinal() {
356         // when
357         FinalClass value = new FinalClass();
358         given(person.getFinalClass()).willReturn(value);
359 
360         // then
361         assertEquals(value, person.getFinalClass());
362     }
363 
364     @Test
deep_stub_does_not_try_to_mock_generic_final_classes()365     public void deep_stub_does_not_try_to_mock_generic_final_classes() {
366         First first = mock(First.class, RETURNS_DEEP_STUBS);
367         assertNull(first.getString());
368         assertNull(first.getSecond().get(0));
369     }
370 
371     @Test
deep_stub_does_not_stack_overflow_on_reversed_generics()372     public void deep_stub_does_not_stack_overflow_on_reversed_generics() {
373         SuperOfReversedGenerics mock = mock(SuperOfReversedGenerics.class, RETURNS_DEEP_STUBS);
374 
375         when((Object) mock.reverse().finalMethod()).thenReturn(5L);
376 
377         assertThat(mock.reverse().finalMethod()).isEqualTo(5L);
378     }
379 }
380