package com.opengamma.sesame;
import static org.mockito.Mockito.mock;
import java.util.Arrays;
import java.util.List;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.google.common.collect.Lists;
import com.google.common.collect.MutableClassToInstanceMap;
import com.opengamma.sesame.engine.ComponentMap;
/**
* Utils for mocking. Creates mock maps useful for insertion in
* {@link ComponentMap}. Note, strict features are not threadsafe.
*/
public final class MockUtils {
private MockUtils() {}
/**
* Returns a map of mock instances, indexed by class.
* @param classes the classes to use to mock
* @return a map of class to mock
*/
public static MutableClassToInstanceMap<Object> mocks(Class<?>...classes ) {
return doMock(Arrays.asList(classes), false);
}
/**
* Returns a map of mock instances, indexed by class.
* @param classes the classes to use to mock
* @return a map of class to mock
*/
public static MutableClassToInstanceMap<Object> mocks(List<Class<?>> classes ) {
return doMock(classes, false);
}
/**
* Returns a map of strict mock instances, indexed by class.
* @param classes the classes to use to mock
* @return a map of class to mock
*/
public static MutableClassToInstanceMap<Object> strictMocks(List<Class<?>> classes ) {
return doMock(classes, true);
}
/**
* Returns a map of strict mock instances, indexed by class.
* @param classes the classes to use to mock
* @return a map of class to mock
*/
public static MutableClassToInstanceMap<Object> strictMocks(Class<?>... classes) {
return doMock(Arrays.asList(classes), true);
}
private static MutableClassToInstanceMap<Object> doMock(List<Class<?>> classes, boolean isStrict) {
MutableClassToInstanceMap<Object> mocks = MutableClassToInstanceMap.create();
for (Class<?> clazz : classes) {
if (isStrict) {
mocks.put(clazz, strictMock(clazz));
} else {
mocks.put(clazz, mock(clazz));
}
}
return mocks;
}
/**
* Creates a 'strict' mock, i.e. a mock which throws if
* called with an un-mocked method.
* @param clazz the class to mock
* @return the mock
*/
public static <T> T strictMock(Class<T> clazz) {
return mock(clazz, new FailAnswer());
}
private static final List<FailAnswer> _allAnswers = Lists.newArrayList();
/**
* Enable strict mode in all registered mocks.
*/
public static void enableStrict() {
for (FailAnswer answer : _allAnswers) {
answer._strictEnabled = true;
}
}
private static class FailAnswer implements Answer<Void> {
private boolean _strictEnabled = false;
private FailAnswer(){
_allAnswers.add(this);
}
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
if (_strictEnabled) {
throw new IllegalStateException(invocation.getMethod() + " not implemented for args " + Arrays.toString(invocation.getArguments()));
} else {
return null;
}
}
}
}