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