1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5
6package org.mockito.internal;
7
8import org.junit.After;
9import org.junit.Test;
10import org.mockito.Mock;
11import org.mockito.StateMaster;
12import org.mockito.exceptions.misusing.InvalidUseOfMatchersException;
13import org.mockito.exceptions.misusing.UnfinishedStubbingException;
14import org.mockito.exceptions.misusing.UnfinishedVerificationException;
15import org.mockitousage.IMethods;
16import org.mockitoutil.TestBase;
17
18import static junit.framework.TestCase.assertEquals;
19import static junit.framework.TestCase.fail;
20import static org.mockito.Mockito.*;
21
22/**
23 * invalid state happens if:
24 *
25 *    -unfinished stubbing
26 *    -unfinished doReturn()
27 *    -stubbing without actual method call
28 *    -verify without actual method call
29 *
30 * we should aim to detect invalid state in following scenarios:
31 *
32 *    -on method call on mock
33 *    -on verify
34 *    -on verifyZeroInteractions
35 *    -on verifyNoMoreInteractions
36 *    -on verify in order
37 *    -on stub
38 */
39@SuppressWarnings({"unchecked", "deprecation"})
40public class InvalidStateDetectionTest extends TestBase {
41
42    @Mock private IMethods mock;
43
44    @After
45    public void resetState() {
46        super.resetState();
47    }
48
49    @Test
50    public void shouldDetectUnfinishedStubbing() {
51        when(mock.simpleMethod());
52        detectsAndCleansUp(new OnMethodCallOnMock(), UnfinishedStubbingException.class);
53
54        when(mock.simpleMethod());
55        detectsAndCleansUp(new OnStub(), UnfinishedStubbingException.class);
56
57        when(mock.simpleMethod());
58        detectsAndCleansUp(new OnVerify(), UnfinishedStubbingException.class);
59
60        when(mock.simpleMethod());
61        detectsAndCleansUp(new OnVerifyInOrder(), UnfinishedStubbingException.class);
62
63        when(mock.simpleMethod());
64        detectsAndCleansUp(new OnVerifyZeroInteractions(), UnfinishedStubbingException.class);
65
66        when(mock.simpleMethod());
67        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), UnfinishedStubbingException.class);
68
69        when(mock.simpleMethod());
70        detectsAndCleansUp(new OnDoAnswer(), UnfinishedStubbingException.class);
71    }
72
73    @Test
74    public void shouldDetectUnfinishedDoAnswerStubbing() {
75        doAnswer(null);
76        detectsAndCleansUp(new OnMethodCallOnMock(), UnfinishedStubbingException.class);
77
78        doAnswer(null);
79        detectsAndCleansUp(new OnStub(), UnfinishedStubbingException.class);
80
81        doAnswer(null);
82        detectsAndCleansUp(new OnVerify(), UnfinishedStubbingException.class);
83
84        doAnswer(null);
85        detectsAndCleansUp(new OnVerifyInOrder(), UnfinishedStubbingException.class);
86
87        doAnswer(null);
88        detectsAndCleansUp(new OnVerifyZeroInteractions(), UnfinishedStubbingException.class);
89
90        doAnswer(null);
91        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), UnfinishedStubbingException.class);
92
93        doAnswer(null);
94        detectsAndCleansUp(new OnDoAnswer(), UnfinishedStubbingException.class);
95    }
96
97    @Test
98    public void shouldDetectUnfinishedVerification() {
99        verify(mock);
100        detectsAndCleansUp(new OnStub(), UnfinishedVerificationException.class);
101
102        verify(mock);
103        detectsAndCleansUp(new OnVerify(), UnfinishedVerificationException.class);
104
105        verify(mock);
106        detectsAndCleansUp(new OnVerifyInOrder(), UnfinishedVerificationException.class);
107
108        verify(mock);
109        detectsAndCleansUp(new OnVerifyZeroInteractions(), UnfinishedVerificationException.class);
110
111        verify(mock);
112        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), UnfinishedVerificationException.class);
113
114        verify(mock);
115        detectsAndCleansUp(new OnDoAnswer(), UnfinishedVerificationException.class);
116    }
117
118    @Test
119    public void shouldDetectMisplacedArgumentMatcher() {
120        anyObject();
121        detectsAndCleansUp(new OnVerify(), InvalidUseOfMatchersException.class);
122
123        anyObject();
124        detectsAndCleansUp(new OnVerifyInOrder(), InvalidUseOfMatchersException.class);
125
126        anyObject();
127        detectsAndCleansUp(new OnVerifyZeroInteractions(), InvalidUseOfMatchersException.class);
128
129        anyObject();
130        detectsAndCleansUp(new OnVerifyNoMoreInteractions(), InvalidUseOfMatchersException.class);
131
132        anyObject();
133        detectsAndCleansUp(new OnDoAnswer(), InvalidUseOfMatchersException.class);
134    }
135
136    @Test
137    public void shouldCorrectStateAfterDetectingUnfinishedStubbing() {
138        doThrow(new RuntimeException()).when(mock);
139
140        try {
141        	doThrow(new RuntimeException()).when(mock).oneArg(true);
142            fail();
143        } catch (UnfinishedStubbingException e) {}
144
145        doThrow(new RuntimeException()).when(mock).oneArg(true);
146        try {
147            mock.oneArg(true);
148            fail();
149        } catch (RuntimeException e) {}
150    }
151
152    @Test
153    public void shouldCorrectStateAfterDetectingUnfinishedVerification() {
154        mock.simpleMethod();
155        verify(mock);
156
157        try {
158            verify(mock).simpleMethod();
159            fail();
160        } catch (UnfinishedVerificationException e) {}
161
162        verify(mock).simpleMethod();
163    }
164
165    private interface DetectsInvalidState {
166        void detect(IMethods mock);
167    }
168
169    private static class OnVerify implements DetectsInvalidState {
170        public void detect(IMethods mock) {
171            verify(mock);
172        }
173    }
174
175    private static class OnVerifyInOrder implements DetectsInvalidState {
176        public void detect(IMethods mock) {
177            inOrder(mock).verify(mock);
178        }
179    }
180
181    private static class OnVerifyZeroInteractions implements DetectsInvalidState {
182        public void detect(IMethods mock) {
183            verifyZeroInteractions(mock);
184        }
185    }
186
187    private static class OnVerifyNoMoreInteractions implements DetectsInvalidState {
188        public void detect(IMethods mock) {
189            verifyNoMoreInteractions(mock);
190        }
191    }
192
193    private static class OnDoAnswer implements DetectsInvalidState {
194        public void detect(IMethods mock) {
195            doAnswer(null);
196        }
197    }
198
199    private static class OnStub implements DetectsInvalidState {
200        public void detect(IMethods mock) {
201            when(mock);
202        }
203    }
204
205    private static class OnMethodCallOnMock implements DetectsInvalidState {
206        public void detect(IMethods mock) {
207            mock.simpleMethod();
208        }
209    }
210
211    private static class OnMockCreation implements DetectsInvalidState {
212        public void detect(IMethods mock) {
213            mock(IMethods.class);
214        }
215    }
216
217    private static class OnSpyCreation implements DetectsInvalidState {
218        public void detect(IMethods mock) {
219            spy(new Object());
220        }
221    }
222
223    private void detectsAndCleansUp(DetectsInvalidState detector, Class<?> expected) {
224        try {
225            detector.detect(mock);
226            fail("Should throw an exception");
227        } catch (Exception e) {
228            assertEquals(expected, e.getClass());
229        }
230        //Make sure state is cleaned up
231        new StateMaster().validate();
232    }
233}
234