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