blob: 851d4a43adaa14b99c1fb2a2a57d23e491e4805b [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.dx.mockito.inline.extended;
import org.mockito.Mockito;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
import java.util.ArrayList;
import java.util.HashMap;
import static com.android.dx.mockito.inline.InlineStaticMockMaker.mockingInProgressClass;
/**
* Same as {@link MockitoSession} but used when static methods are also stubbed.
*/
@UnstableApi
public class StaticMockitoSession implements MockitoSession {
/**
* For each class where static mocking is enabled there is one marker object.
*/
private static final HashMap<Class, Object> classToMarker = new HashMap<>();
private final MockitoSession instanceSession;
private final ArrayList<Class<?>> staticMocks = new ArrayList<>(0);
StaticMockitoSession(MockitoSession instanceSession) {
ExtendedMockito.addSession(this);
this.instanceSession = instanceSession;
}
@Override
public void setStrictness(Strictness strictness) {
instanceSession.setStrictness(strictness);
}
/**
* {@inheritDoc}
* <p><b>Extension:</b> This also resets all stubbing of static methods set up in the
* {@link ExtendedMockito#mockitoSession() builder} of the session.
*/
@Override
public void finishMocking() {
finishMocking(null);
}
/**
* {@inheritDoc}
* <p><b>Extension:</b> This also resets all stubbing of static methods set up in the
* {@link ExtendedMockito#mockitoSession() builder} of the session.
*/
@Override
public void finishMocking(Throwable failure) {
try {
instanceSession.finishMocking(failure);
} finally {
for (Class<?> clazz : staticMocks) {
mockingInProgressClass.set(clazz);
try {
Mockito.reset(ExtendedMockito.staticMockMarker(clazz));
} finally {
mockingInProgressClass.remove();
}
classToMarker.remove(clazz);
}
ExtendedMockito.removeSession(this);
}
}
/**
* Init mocking for a class.
*
* @param mocking Description and settings of the mocking
* @param <T> The class to mock
*/
<T> void mockStatic(StaticMocking<T> mocking) {
if (ExtendedMockito.staticMockMarker(mocking.clazz) != null) {
throw new IllegalArgumentException(mocking.clazz + " is already mocked");
}
mockingInProgressClass.set(mocking.clazz);
try {
classToMarker.put(mocking.clazz, mocking.markerSupplier.get());
} finally {
mockingInProgressClass.remove();
}
staticMocks.add(mocking.clazz);
}
/**
* Get marker for a mocked/spies class or {@code null}.
*
* @param clazz The class that is mocked
* @return marker for a mocked class or {@code null} if class is not mocked in this session
* @see ExtendedMockito#staticMockMarker(Class)
*/
@SuppressWarnings("unchecked")
<T> T staticMockMarker(Class<T> clazz) {
return (T) classToMarker.get(clazz);
}
}