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.stubbing;
7 
8 import static org.junit.Assert.assertEquals;
9 import static org.junit.Assert.assertNull;
10 import static org.junit.Assert.assertTrue;
11 import static org.junit.Assert.fail;
12 import static org.hamcrest.CoreMatchers.sameInstance;
13 import static org.mockito.Mockito.doThrow;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.verify;
16 import static org.mockito.Mockito.verifyNoMoreInteractions;
17 import static org.mockito.Mockito.verifyZeroInteractions;
18 import static org.mockito.Mockito.when;
19 
20 import java.io.IOException;
21 import java.io.Reader;
22 import java.util.HashMap;
23 import java.util.LinkedList;
24 import java.util.Map;
25 
26 import org.assertj.core.api.Assertions;
27 import org.assertj.core.api.ThrowableAssert;
28 import org.junit.Before;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.rules.ExpectedException;
32 import org.mockito.exceptions.base.MockitoException;
33 import org.mockito.exceptions.verification.NoInteractionsWanted;
34 import org.mockito.exceptions.verification.WantedButNotInvoked;
35 import org.mockitousage.IMethods;
36 import org.mockitoutil.TestBase;
37 
38 @SuppressWarnings({ "serial", "unchecked", "rawtypes" })
39 public class StubbingWithThrowablesTest extends TestBase {
40 
41     private LinkedList mock;
42 
43     private Map mockTwo;
44 
45     @Rule
46     public ExpectedException exception = ExpectedException.none();
47 
48     @Before
setup()49     public void setup() {
50         mock = mock(LinkedList.class);
51         mockTwo = mock(HashMap.class);
52     }
53 
54     @Test
throws_same_exception_consecutively()55     public void throws_same_exception_consecutively() {
56         when(mock.add("")).thenThrow(new ExceptionOne());
57 
58         //1st invocation
59         Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
60             public void call() {
61                 mock.add("");
62             }
63         }).isInstanceOf(ExceptionOne.class);
64 
65         mock.add("1");
66 
67         //2nd invocation
68         Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
69             public void call() {
70                 mock.add("");
71             }
72         }).isInstanceOf(ExceptionOne.class);
73     }
74 
75     @Test
throws_same_exception_consecutively_with_doThrow()76     public void throws_same_exception_consecutively_with_doThrow() {
77         doThrow(new ExceptionOne()).when(mock).clear();
78 
79         //1st invocation
80         Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
81             public void call() {
82                 mock.clear();
83             }
84         }).isInstanceOf(ExceptionOne.class);
85 
86         mock.add("1");
87 
88         //2nd invocation
89         Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() {
90             public void call() {
91                 mock.clear();
92             }
93         }).isInstanceOf(ExceptionOne.class);
94     }
95 
96     @Test
shouldStubWithThrowable()97     public void shouldStubWithThrowable() throws Exception {
98         IllegalArgumentException expected = new IllegalArgumentException("thrown by mock");
99         when(mock.add("throw")).thenThrow(expected);
100 
101         exception.expect(sameInstance(expected));
102         mock.add("throw");
103     }
104 
105     @Test
shouldSetThrowableToVoidMethod()106     public void shouldSetThrowableToVoidMethod() throws Exception {
107         IllegalArgumentException expected = new IllegalArgumentException("thrown by mock");
108 
109         doThrow(expected).when(mock).clear();
110 
111         exception.expect(sameInstance(expected));
112 
113         mock.clear();
114 
115     }
116 
117     @Test
shouldLastStubbingVoidBeImportant()118     public void shouldLastStubbingVoidBeImportant() throws Exception {
119         doThrow(new ExceptionOne()).when(mock).clear();
120         doThrow(new ExceptionTwo()).when(mock).clear();
121 
122         exception.expect(ExceptionTwo.class);
123 
124         mock.clear();
125     }
126 
127     @Test
shouldFailStubbingThrowableOnTheSameInvocationDueToAcceptableLimitation()128     public void shouldFailStubbingThrowableOnTheSameInvocationDueToAcceptableLimitation() throws Exception {
129         when(mock.size()).thenThrow(new ExceptionOne());
130 
131         exception.expect(ExceptionOne.class);
132 
133         when(mock.size()).thenThrow(new ExceptionTwo());
134     }
135 
136     @Test
shouldAllowSettingCheckedException()137     public void shouldAllowSettingCheckedException() throws Exception {
138         Reader reader = mock(Reader.class);
139         IOException ioException = new IOException();
140 
141         when(reader.read()).thenThrow(ioException);
142 
143         exception.expect(sameInstance(ioException));
144 
145         reader.read();
146     }
147 
148     @Test
shouldAllowSettingError()149     public void shouldAllowSettingError() throws Exception {
150         Error error = new Error();
151 
152         when(mock.add("quake")).thenThrow(error);
153 
154         exception.expect(Error.class);
155 
156         mock.add("quake");
157     }
158 
159     @Test
shouldNotAllowNullExceptionType()160     public void shouldNotAllowNullExceptionType() {
161         exception.expect(MockitoException.class);
162         exception.expectMessage("Cannot stub with null throwable");
163 
164         when(mock.add(null)).thenThrow((Exception) null);
165     }
166 
167     @Test
shouldInstantiateExceptionClassOnInteraction()168     public void shouldInstantiateExceptionClassOnInteraction() {
169         when(mock.add(null)).thenThrow(NaughtyException.class);
170 
171         exception.expect(NaughtyException.class);
172 
173         mock.add(null);
174     }
175 
176     @Test
shouldInstantiateExceptionClassWithOngoingStubbingOnInteraction()177     public void shouldInstantiateExceptionClassWithOngoingStubbingOnInteraction() {
178         doThrow(NaughtyException.class).when(mock).add(null);
179 
180         exception.expect(NaughtyException.class);
181 
182         mock.add(null);
183     }
184 
185     @Test
shouldNotAllowSettingInvalidCheckedException()186     public void shouldNotAllowSettingInvalidCheckedException() {
187         exception.expect(MockitoException.class);
188         exception.expectMessage("Checked exception is invalid for this method");
189 
190         when(mock.add("monkey island")).thenThrow(new Exception());
191     }
192 
193     @Test
shouldNotAllowSettingNullThrowable()194     public void shouldNotAllowSettingNullThrowable() {
195         exception.expect(MockitoException.class);
196         exception.expectMessage("Cannot stub with null throwable");
197 
198         when(mock.add("monkey island")).thenThrow((Throwable) null);
199     }
200 
201     @Test
shouldNotAllowSettingNullThrowableArray()202     public void shouldNotAllowSettingNullThrowableArray() {
203         exception.expect(MockitoException.class);
204         exception.expectMessage("Cannot stub with null throwable");
205 
206         when(mock.add("monkey island")).thenThrow((Throwable[]) null);
207     }
208 
209     @Test
shouldNotAllowSettingNullThrowableClass()210     public void shouldNotAllowSettingNullThrowableClass() {
211         exception.expect(MockitoException.class);
212         exception.expectMessage("Exception type cannot be null");
213 
214         when(mock.isEmpty()).thenThrow((Class) null);
215     }
216 
217     @Test
shouldNotAllowSettingNullThrowableClasses()218     public void shouldNotAllowSettingNullThrowableClasses() {
219         exception.expect(MockitoException.class);
220         exception.expectMessage("Exception type cannot be null");
221 
222         when(mock.isEmpty()).thenThrow(RuntimeException.class, (Class[]) null);
223     }
224 
225     @Test
shouldNotAllowSettingNullVarArgThrowableClass()226     public void shouldNotAllowSettingNullVarArgThrowableClass() {
227         exception.expect(MockitoException.class);
228         exception.expectMessage("Exception type cannot be null");
229 
230         when(mock.isEmpty()).thenThrow(RuntimeException.class, (Class) null);
231     }
232 
233     @Test
doThrowShouldNotAllowSettingNullThrowableClass()234     public void doThrowShouldNotAllowSettingNullThrowableClass() {
235         exception.expect(MockitoException.class);
236         exception.expectMessage("Exception type cannot be null");
237 
238         doThrow((Class) null).when(mock).isEmpty();
239     }
240 
241     @Test
doThrowShouldNotAllowSettingNullThrowableClasses()242     public void doThrowShouldNotAllowSettingNullThrowableClasses() throws Exception {
243         exception.expect(MockitoException.class);
244         exception.expectMessage("Exception type cannot be null");
245 
246         doThrow(RuntimeException.class, (Class) null).when(mock).isEmpty();
247     }
248 
249     @Test
doThrowShouldNotAllowSettingNullVarArgThrowableClasses()250     public void doThrowShouldNotAllowSettingNullVarArgThrowableClasses() throws Exception {
251         exception.expect(MockitoException.class);
252         exception.expectMessage("Exception type cannot be null");
253 
254         doThrow(RuntimeException.class, (Class[]) null).when(mock).isEmpty();
255     }
256 
257     @Test
shouldNotAllowSettingNullVarArgsThrowableClasses()258     public void shouldNotAllowSettingNullVarArgsThrowableClasses() throws Exception {
259         exception.expect(MockitoException.class);
260         exception.expectMessage("Exception type cannot be null");
261 
262         when(mock.isEmpty()).thenThrow(RuntimeException.class, (Class<RuntimeException>[]) null);
263     }
264 
265     @Test
shouldNotAllowDifferntCheckedException()266     public void shouldNotAllowDifferntCheckedException() throws Exception {
267         IMethods mock = mock(IMethods.class);
268 
269         exception.expect(MockitoException.class);
270         exception.expectMessage("Checked exception is invalid for this method");
271 
272         when(mock.throwsIOException(0)).thenThrow(CheckedException.class);
273     }
274 
275     @Test
shouldNotAllowCheckedExceptionWhenErrorIsDeclared()276     public void shouldNotAllowCheckedExceptionWhenErrorIsDeclared() throws Exception {
277         IMethods mock = mock(IMethods.class);
278 
279         exception.expect(MockitoException.class);
280         exception.expectMessage("Checked exception is invalid for this method");
281 
282         when(mock.throwsError(0)).thenThrow(CheckedException.class);
283     }
284 
285     @Test
shouldNotAllowCheckedExceptionWhenNothingIsDeclared()286     public void shouldNotAllowCheckedExceptionWhenNothingIsDeclared() throws Exception {
287         IMethods mock = mock(IMethods.class);
288 
289         exception.expect(MockitoException.class);
290         exception.expectMessage("Checked exception is invalid for this method");
291 
292         when(mock.throwsNothing(true)).thenThrow(CheckedException.class);
293     }
294 
295     @Test
shouldMixThrowablesAndReturnsOnDifferentMocks()296     public void shouldMixThrowablesAndReturnsOnDifferentMocks() throws Exception {
297         when(mock.add("ExceptionOne")).thenThrow(new ExceptionOne());
298         when(mock.getLast()).thenReturn("last");
299         doThrow(new ExceptionTwo()).when(mock).clear();
300 
301         doThrow(new ExceptionThree()).when(mockTwo).clear();
302         when(mockTwo.containsValue("ExceptionFour")).thenThrow(new ExceptionFour());
303         when(mockTwo.get("Are you there?")).thenReturn("Yes!");
304 
305         assertNull(mockTwo.get("foo"));
306         assertTrue(mockTwo.keySet().isEmpty());
307         assertEquals("Yes!", mockTwo.get("Are you there?"));
308         try {
309             mockTwo.clear();
310             fail();
311         } catch (ExceptionThree e) {
312         }
313         try {
314             mockTwo.containsValue("ExceptionFour");
315             fail();
316         } catch (ExceptionFour e) {
317         }
318 
319         assertNull(mock.getFirst());
320         assertEquals("last", mock.getLast());
321         try {
322             mock.add("ExceptionOne");
323             fail();
324         } catch (ExceptionOne e) {
325         }
326         try {
327             mock.clear();
328             fail();
329         } catch (ExceptionTwo e) {
330         }
331     }
332 
333     @Test
shouldStubbingWithThrowableBeVerifiable()334     public void shouldStubbingWithThrowableBeVerifiable() {
335         when(mock.size()).thenThrow(new RuntimeException());
336         doThrow(new RuntimeException()).when(mock).clone();
337 
338         try {
339             mock.size();
340             fail();
341         } catch (RuntimeException e) {
342         }
343 
344         try {
345             mock.clone();
346             fail();
347         } catch (RuntimeException e) {
348         }
349 
350         verify(mock).size();
351         verify(mock).clone();
352         verifyNoMoreInteractions(mock);
353     }
354 
355     @Test
shouldStubbingWithThrowableFailVerification()356     public void shouldStubbingWithThrowableFailVerification() {
357         when(mock.size()).thenThrow(new RuntimeException());
358         doThrow(new RuntimeException()).when(mock).clone();
359 
360         verifyZeroInteractions(mock);
361 
362         mock.add("test");
363 
364         try {
365             verify(mock).size();
366             fail();
367         } catch (WantedButNotInvoked e) {
368         }
369 
370         try {
371             verify(mock).clone();
372             fail();
373         } catch (WantedButNotInvoked e) {
374         }
375 
376         try {
377             verifyNoMoreInteractions(mock);
378             fail();
379         } catch (NoInteractionsWanted e) {
380         }
381     }
382 
383     private class ExceptionOne extends RuntimeException {
384     }
385 
386     private class ExceptionTwo extends RuntimeException {
387     }
388 
389     private class ExceptionThree extends RuntimeException {
390     }
391 
392     private class ExceptionFour extends RuntimeException {
393     }
394 
395     private class CheckedException extends Exception {
396     }
397 
398     public class NaughtyException extends RuntimeException {
NaughtyException()399         public NaughtyException() {
400             throw new RuntimeException("boo!");
401         }
402     }
403 }
404