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