• 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 
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