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.strictness; 7 8 import org.assertj.core.api.ThrowableAssert; 9 import org.junit.After; 10 import org.junit.Before; 11 import org.junit.Test; 12 import org.mockito.AdditionalAnswers; 13 import org.mockito.Mock; 14 import org.mockito.Mockito; 15 import org.mockito.MockitoSession; 16 import org.mockito.exceptions.misusing.PotentialStubbingProblem; 17 import org.mockito.exceptions.misusing.UnnecessaryStubbingException; 18 import org.mockito.exceptions.verification.NoInteractionsWanted; 19 import org.mockito.quality.Strictness; 20 import org.mockitousage.IMethods; 21 import org.mockitoutil.TestBase; 22 23 import static org.assertj.core.api.Assertions.assertThatThrownBy; 24 import static org.junit.Assert.assertEquals; 25 import static org.mockito.Mockito.lenient; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.spy; 28 import static org.mockito.Mockito.verifyNoMoreInteractions; 29 import static org.mockito.Mockito.when; 30 31 public class StrictnessPerStubbingTest { 32 33 MockitoSession mockito; 34 @Mock IMethods mock; 35 36 @Before before()37 public void before() { 38 mockito = Mockito.mockitoSession().initMocks(this).strictness(Strictness.STRICT_STUBS).startMocking(); 39 } 40 41 @Test potential_stubbing_problem()42 public void potential_stubbing_problem() { 43 //when 44 when(mock.simpleMethod("1")).thenReturn("1"); 45 lenient().when(mock.differentMethod("2")).thenReturn("2"); 46 47 //then on lenient stubbing, we can call it with different argument: 48 mock.differentMethod("200"); 49 50 //but on strict stubbing, we cannot: 51 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 52 @Override 53 public void call() throws Throwable { 54 mock.simpleMethod("100"); 55 } 56 }).isInstanceOf(PotentialStubbingProblem.class); 57 } 58 59 @Test doReturn_syntax()60 public void doReturn_syntax() { 61 //when 62 lenient().doReturn("2").doReturn("3") 63 .when(mock).simpleMethod(1); 64 65 //then on lenient stubbing, we can call it with different argument: 66 mock.simpleMethod(200); 67 68 //and stubbing works, too: 69 assertEquals("2", mock.simpleMethod(1)); 70 assertEquals("3", mock.simpleMethod(1)); 71 } 72 73 @Test doReturn_varargs_syntax()74 public void doReturn_varargs_syntax() { 75 //when 76 lenient().doReturn("2", "3") 77 .when(mock).simpleMethod(1); 78 79 //then on lenient stubbing, we can call it with different argument with no exception: 80 mock.simpleMethod(200); 81 82 //and stubbing works, too: 83 assertEquals("2", mock.simpleMethod(1)); 84 assertEquals("3", mock.simpleMethod(1)); 85 } 86 87 @Test doThrow_syntax()88 public void doThrow_syntax() { 89 //when 90 lenient() 91 .doThrow(IllegalArgumentException.class) 92 .doThrow(IllegalStateException.class) 93 .when(mock).simpleMethod(1); 94 95 //then on lenient stubbing, we can call it with different argument with no exception: 96 mock.simpleMethod(200); 97 98 //and stubbing works, too: 99 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 100 public void call() throws Throwable { 101 mock.simpleMethod(1); 102 } 103 }).isInstanceOf(IllegalArgumentException.class); 104 105 //testing consecutive call: 106 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 107 public void call() throws Throwable { 108 mock.simpleMethod(1); 109 } 110 }).isInstanceOf(IllegalStateException.class); 111 } 112 113 @Test doThrow_vararg_syntax()114 public void doThrow_vararg_syntax() { 115 //when 116 lenient() 117 .doThrow(IllegalArgumentException.class, IllegalStateException.class) 118 .when(mock).simpleMethod(1); 119 120 //then on lenient stubbing, we can call it with different argument with no exception: 121 mock.simpleMethod(200); 122 123 //and stubbing works, too: 124 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 125 public void call() throws Throwable { 126 mock.simpleMethod(1); 127 } 128 }).isInstanceOf(IllegalArgumentException.class); 129 130 //testing consecutive call: 131 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 132 public void call() throws Throwable { 133 mock.simpleMethod(1); 134 } 135 }).isInstanceOf(IllegalStateException.class); 136 } 137 138 @Test doThrow_instance_vararg_syntax()139 public void doThrow_instance_vararg_syntax() { 140 //when 141 lenient() 142 .doThrow(new IllegalArgumentException(), new IllegalStateException()) 143 .when(mock).simpleMethod(1); 144 145 //then on lenient stubbing, we can call it with different argument with no exception: 146 mock.simpleMethod(200); 147 148 //and stubbing works, too: 149 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 150 public void call() throws Throwable { 151 mock.simpleMethod(1); 152 } 153 }).isInstanceOf(IllegalArgumentException.class); 154 155 //testing consecutive call: 156 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 157 public void call() throws Throwable { 158 mock.simpleMethod(1); 159 } 160 }).isInstanceOf(IllegalStateException.class); 161 } 162 163 static class Counter { increment(int x)164 int increment(int x) { 165 return x + 1; 166 } scream(String message)167 void scream(String message) { 168 throw new RuntimeException(message); 169 } 170 } 171 172 @Test doCallRealMethod_syntax()173 public void doCallRealMethod_syntax() { 174 //when 175 Counter mock = mock(Counter.class); 176 lenient().doCallRealMethod().when(mock).increment(1); 177 178 //then no exception and default return value if we call it with different arg: 179 assertEquals(0, mock.increment(0)); 180 181 //and real method is called when using correct arg: 182 assertEquals(2, mock.increment(1)); 183 } 184 185 @Test doNothing_syntax()186 public void doNothing_syntax() { 187 //when 188 final Counter spy = spy(Counter.class); 189 lenient().doNothing().when(spy).scream("1"); 190 191 //then no stubbing exception and real method is called if we call stubbed method with different arg: 192 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 193 @Override 194 public void call() throws Throwable { 195 spy.scream("2"); 196 } 197 }).hasMessage("2"); 198 199 //and we do nothing when stubbing called with correct arg: 200 spy.scream("1"); 201 } 202 203 @Test doAnswer_syntax()204 public void doAnswer_syntax() { 205 //when 206 lenient().doAnswer(AdditionalAnswers.returnsFirstArg()).when(mock).simpleMethod("1"); 207 208 //then on lenient stubbing, we can call it with different argument: 209 mock.simpleMethod("200"); 210 211 //and stubbing works, too: 212 assertEquals("1", mock.simpleMethod("1")); 213 } 214 215 @Test unnecessary_stubbing()216 public void unnecessary_stubbing() { 217 //when 218 when(mock.simpleMethod("1")).thenReturn("1"); 219 lenient().when(mock.differentMethod("2")).thenReturn("2"); 220 221 //then unnecessary stubbing flags method only on the strict stubbing: 222 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 223 @Override 224 public void call() throws Throwable { 225 mockito.finishMocking(); 226 } 227 }).isInstanceOf(UnnecessaryStubbingException.class) 228 .hasMessageContaining("1. -> ") 229 //good enough to prove that we're flagging just one unnecessary stubbing: 230 //TODO 792: this assertion is duplicated with StrictnessPerMockTest 231 .isNot(TestBase.hasMessageContaining("2. ->")); 232 } 233 234 @Test unnecessary_stubbing_with_doReturn()235 public void unnecessary_stubbing_with_doReturn() { 236 //when 237 lenient().doReturn("2").when(mock).differentMethod("2"); 238 239 //then no exception is thrown: 240 mockito.finishMocking(); 241 } 242 243 @Test verify_no_more_invocations()244 public void verify_no_more_invocations() { 245 //when 246 when(mock.simpleMethod("1")).thenReturn("1"); 247 lenient().when(mock.differentMethod("2")).thenReturn("2"); 248 249 //and: 250 mock.simpleMethod("1"); 251 mock.differentMethod("200"); // <- different arg 252 253 //then 'verifyNoMoreInteractions' flags the lenient stubbing (called with different arg) 254 //and reports it with [?] in the exception message 255 assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { 256 @Override 257 public void call() throws Throwable { 258 verifyNoMoreInteractions(mock); 259 } 260 }).isInstanceOf(NoInteractionsWanted.class) 261 .hasMessageContaining("1. ->") 262 .hasMessageContaining("2. [?]->"); 263 //TODO 792: assertion duplicated with StrictnessPerMockTest 264 // and we should use assertions based on content of the exception rather than the string 265 } 266 267 @After after()268 public void after() { 269 mockito.finishMocking(); 270 } 271 } 272