1e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/*
2e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Copyright (c) 2007 Mockito contributors
3e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * This program is made available under the terms of the MIT License.
4e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */
5e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpackage org.mockito.internal;
6e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
7e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.InOrder;
8e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.MockSettings;
9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.MockingDetails;
10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.exceptions.Reporter;
11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.exceptions.misusing.NotAMockException;
12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.creation.MockSettingsImpl;
13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.invocation.finder.VerifiableInvocationsFinder;
14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.progress.IOngoingStubbing;
15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.progress.MockingProgress;
16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.progress.ThreadSafeMockingProgress;
17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.stubbing.InvocationContainer;
18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.stubbing.OngoingStubbingImpl;
19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.stubbing.StubberImpl;
20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.util.DefaultMockingDetails;
21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.util.MockUtil;
22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.verification.MockAwareVerificationMode;
23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.verification.VerificationDataImpl;
24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.verification.VerificationModeFactory;
25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.verification.api.InOrderContext;
26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.verification.api.VerificationDataInOrder;
27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.verification.api.VerificationDataInOrderImpl;
28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.invocation.Invocation;
29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.mock.MockCreationSettings;
30e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.stubbing.*;
31e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.verification.VerificationMode;
32e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
33e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.Arrays;
34e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.util.List;
35e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
36e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson@SuppressWarnings("unchecked")
37e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpublic class MockitoCore {
38e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
39e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    private final Reporter reporter = new Reporter();
40e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    private final MockUtil mockUtil = new MockUtil();
41e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    private final MockingProgress mockingProgress = new ThreadSafeMockingProgress();
42e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
43e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public boolean isTypeMockable(Class<?> typeToMock) {
44e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return mockUtil.isTypeMockable(typeToMock);
45e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
46e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
47e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public <T> T mock(Class<T> typeToMock, MockSettings settings) {
48e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        if (!MockSettingsImpl.class.isInstance(settings)) {
49e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            throw new IllegalArgumentException(
50e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    "Unexpected implementation of '" + settings.getClass().getCanonicalName() + "'\n"
51e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    + "At the moment, you cannot provide your own implementations that class.");
52e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
53e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        MockSettingsImpl impl = MockSettingsImpl.class.cast(settings);
54e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        MockCreationSettings<T> creationSettings = impl.confirm(typeToMock);
55e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        T mock = mockUtil.createMock(creationSettings);
56e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.mockingStarted(mock, typeToMock);
57e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return mock;
58e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
59e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
60e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public IOngoingStubbing stub() {
61e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        IOngoingStubbing stubbing = mockingProgress.pullOngoingStubbing();
62e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        if (stubbing == null) {
63e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            mockingProgress.reset();
64e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            reporter.missingMethodInvocation();
65e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
66e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return stubbing;
67e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
68e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
69e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public <T> DeprecatedOngoingStubbing<T> stub(T methodCall) {
70e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.stubbingStarted();
71e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return (DeprecatedOngoingStubbing) stub();
72e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
73e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
74e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public <T> OngoingStubbing<T> when(T methodCall) {
75e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.stubbingStarted();
76e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return (OngoingStubbing) stub();
77e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
78e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
79e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public <T> T verify(T mock, VerificationMode mode) {
80e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        if (mock == null) {
81e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            reporter.nullPassedToVerify();
82e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        } else if (!mockUtil.isMock(mock)) {
83e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            reporter.notAMockPassedToVerify(mock.getClass());
84e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
85e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, mode));
86e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return mock;
87e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
88e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
89e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public <T> void reset(T ... mocks) {
90e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.validateState();
91e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.reset();
92e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.resetOngoingStubbing();
93e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
94e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        for (T m : mocks) {
95e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            mockUtil.resetMock(m);
96e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
97e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
98e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
99e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public void verifyNoMoreInteractions(Object... mocks) {
100e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        assertMocksNotEmpty(mocks);
101e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.validateState();
102e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        for (Object mock : mocks) {
103e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            try {
104e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                if (mock == null) {
105e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    reporter.nullPassedToVerifyNoMoreInteractions();
106e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                }
107e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                InvocationContainer invocations = mockUtil.getMockHandler(mock).getInvocationContainer();
108e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                VerificationDataImpl data = new VerificationDataImpl(invocations, null);
109e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                VerificationModeFactory.noMoreInteractions().verify(data);
110e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            } catch (NotAMockException e) {
111e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                reporter.notAMockPassedToVerifyNoMoreInteractions();
112e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            }
113e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
114e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
115e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
116e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public void verifyNoMoreInteractionsInOrder(List<Object> mocks, InOrderContext inOrderContext) {
117e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.validateState();
118e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        VerifiableInvocationsFinder finder = new VerifiableInvocationsFinder();
119e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        VerificationDataInOrder data = new VerificationDataInOrderImpl(inOrderContext, finder.find(mocks), null);
120e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        VerificationModeFactory.noMoreInteractions().verifyInOrder(data);
121e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
122e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
123e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    private void assertMocksNotEmpty(Object[] mocks) {
124e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        if (mocks == null || mocks.length == 0) {
125e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            reporter.mocksHaveToBePassedToVerifyNoMoreInteractions();
126e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
127e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
128e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
129e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public InOrder inOrder(Object... mocks) {
130e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        if (mocks == null || mocks.length == 0) {
131e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            reporter.mocksHaveToBePassedWhenCreatingInOrder();
132e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
133e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        for (Object mock : mocks) {
134e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            if (mock == null) {
135e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                reporter.nullPassedWhenCreatingInOrder();
136e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            } else if (!mockUtil.isMock(mock)) {
137e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                reporter.notAMockPassedWhenCreatingInOrder();
138e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            }
139e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
140e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return new InOrderImpl(Arrays.asList(mocks));
141e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
142e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
143e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public Stubber doAnswer(Answer answer) {
144e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.stubbingStarted();
145e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.resetOngoingStubbing();
146e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return new StubberImpl().doAnswer(answer);
147e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
148e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
149e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public <T> VoidMethodStubbable<T> stubVoid(T mock) {
150e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        InternalMockHandler<T> handler = mockUtil.getMockHandler(mock);
151e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.stubbingStarted();
152e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return handler.voidMethodStubbable(mock);
153e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
154e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
155e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public void validateMockitoUsage() {
156e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        mockingProgress.validateState();
157e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
158e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
159e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    /**
160e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * For testing purposes only. Is not the part of main API.
161e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     * @return last invocation
162e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson     */
163e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public Invocation getLastInvocation() {
164e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        OngoingStubbingImpl ongoingStubbing = ((OngoingStubbingImpl) mockingProgress.pullOngoingStubbing());
165e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        List<Invocation> allInvocations = ongoingStubbing.getRegisteredInvocations();
166e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return allInvocations.get(allInvocations.size()-1);
167e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
168e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
169e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public Object[] ignoreStubs(Object... mocks) {
170e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        for (Object m : mocks) {
171e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            InvocationContainer invocationContainer = new MockUtil().getMockHandler(m).getInvocationContainer();
172e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            List<Invocation> ins = invocationContainer.getInvocations();
173e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            for (Invocation in : ins) {
174e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                if (in.stubInfo() != null) {
175e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                    in.ignoreForVerification();
176e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson                }
177e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson            }
178e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        }
179e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return mocks;
180e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
181e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson
182e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    public MockingDetails mockingDetails(Object toInspect) {
183e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson        return new DefaultMockingDetails(toInspect, new MockUtil());
184e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson    }
185e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson}