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.assertj.core.api.Assertions; 9 import org.junit.Before; 10 import org.junit.Test; 11 import org.mockitoutil.TestBase; 12 13 import static junit.framework.TestCase.assertEquals; 14 import static junit.framework.TestCase.fail; 15 import static org.mockito.Mockito.doThrow; 16 import static org.mockito.Mockito.spy; 17 import static org.mockito.Mockito.verify; 18 import static org.mockito.Mockito.when; 19 import static org.mockitoutil.Conditions.methodsInStackTrace; 20 21 @SuppressWarnings("unchecked") 22 public class PartialMockingWithSpiesTest extends TestBase { 23 24 @Before 25 public void pleaseMakeStackTracesClean() { 26 makeStackTracesClean(); 27 } 28 29 class InheritMe { 30 private String inherited = "100$"; 31 protected String getInherited() { 32 return inherited; 33 } 34 } 35 36 class Person extends InheritMe { 37 private final Name defaultName = new Name("Default name"); 38 39 public String getName() { 40 return guessName().name; 41 } 42 43 Name guessName() { 44 return defaultName; 45 } 46 47 public String howMuchDidYouInherit() { 48 return getInherited(); 49 } 50 51 public String getNameButDelegateToMethodThatThrows() { 52 throwSomeException(); 53 return guessName().name; 54 } 55 56 private void throwSomeException() { 57 throw new RuntimeException("boo"); 58 } 59 } 60 61 class Name { 62 private final String name; 63 64 public Name(String name) { 65 this.name = name; 66 } 67 } 68 69 Person spy = spy(new Person()); 70 71 @Test 72 public void shouldCallRealMethdsEvenDelegatedToOtherSelfMethod() { 73 // when 74 String name = spy.getName(); 75 76 // then 77 assertEquals("Default name", name); 78 } 79 80 @Test 81 public void shouldAllowStubbingOfMethodsThatDelegateToOtherMethods() { 82 // when 83 when(spy.getName()).thenReturn("foo"); 84 85 // then 86 assertEquals("foo", spy.getName()); 87 } 88 89 @Test 90 public void shouldAllowStubbingWithThrowablesMethodsThatDelegateToOtherMethods() { 91 // when 92 doThrow(new RuntimeException("appetite for destruction")) 93 .when(spy).getNameButDelegateToMethodThatThrows(); 94 95 // then 96 try { 97 spy.getNameButDelegateToMethodThatThrows(); 98 fail(); 99 } catch(Exception e) { 100 assertEquals("appetite for destruction", e.getMessage()); 101 } 102 } 103 104 @Test 105 public void shouldStackTraceGetFilteredOnUserExceptions() { 106 try { 107 // when 108 spy.getNameButDelegateToMethodThatThrows(); 109 fail(); 110 } catch (Throwable t) { 111 // then 112 Assertions.assertThat(t).has(methodsInStackTrace( 113 "throwSomeException", 114 "getNameButDelegateToMethodThatThrows", 115 "shouldStackTraceGetFilteredOnUserExceptions" 116 )); 117 } 118 } 119 120 // @Test //manual verification 121 public void verifyTheStackTrace() { 122 spy.getNameButDelegateToMethodThatThrows(); 123 } 124 125 @Test 126 public void shouldVerify() { 127 // when 128 spy.getName(); 129 130 // then 131 verify(spy).guessName(); 132 } 133 134 @Test 135 public void shouldStub() { 136 // given 137 when(spy.guessName()).thenReturn(new Name("John")); 138 // when 139 String name = spy.getName(); 140 // then 141 assertEquals("John", name); 142 } 143 144 @Test 145 public void shouldDealWithPrivateFieldsOfSubclasses() { 146 assertEquals("100$", spy.howMuchDidYouInherit()); 147 } 148 } 149