Skip to content

Commit

Permalink
fixup! Fixes mockito#2626 : Introduce MockSettings.mockMaker
Browse files Browse the repository at this point in the history
  • Loading branch information
JojOatXGME committed Aug 30, 2022
1 parent 072d420 commit cac5ffa
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 40 deletions.
Expand Up @@ -83,7 +83,7 @@ public AutoCloseable process(Class<?> context, Object testInstance) {
}

private static Object spyInstance(Field field, Object instance) {
// TODO: Should we also add an option to @Spy?
// TODO: Add mockMaker option for @Spy annotation (#2740)
return Mockito.mock(
instance.getClass(),
withSettings()
Expand All @@ -94,7 +94,7 @@ private static Object spyInstance(Field field, Object instance) {

private static Object spyNewInstance(Object testInstance, Field field)
throws InstantiationException, IllegalAccessException, InvocationTargetException {
// TODO: Should we also add an option to @Spy?
// TODO: Add mockMaker option for @Spy annotation (#2740)
MockSettings settings =
withSettings().defaultAnswer(CALLS_REAL_METHODS).name(field.getName());
Class<?> type = field.getType();
Expand Down
Expand Up @@ -42,7 +42,7 @@ protected boolean processInjection(Field field, Object fieldOwner, Set<Object> m
// B. protect against multiple use of MockitoAnnotations.openMocks()
Mockito.reset(instance);
} else {
// TODO: Should we also add an option to @Spy?
// TODO: Add mockMaker option for @Spy annotation (#2740)
Object mock =
Mockito.mock(
instance.getClass(),
Expand Down
Expand Up @@ -5,7 +5,9 @@
package org.mockito.internal.configuration.plugins;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.mockito.MockMakers;
import org.mockito.plugins.AnnotationEngine;
Expand All @@ -18,12 +20,13 @@
import org.mockito.plugins.PluginSwitch;
import org.mockito.plugins.StackTraceCleanerProvider;

class DefaultMockitoPlugins implements MockitoPlugins {
public class DefaultMockitoPlugins implements MockitoPlugins {

private static final Map<String, String> DEFAULT_PLUGINS = new HashMap<>();
static final String INLINE_ALIAS = MockMakers.INLINE;
static final String PROXY_ALIAS = MockMakers.PROXY;
static final String SUBCLASS_ALIAS = MockMakers.SUBCLASS;
public static final Set<String> MOCK_MAKER_ALIASES = new HashSet<>();
static final String MODULE_ALIAS = "member-accessor-module";

static {
Expand Down Expand Up @@ -56,6 +59,10 @@ class DefaultMockitoPlugins implements MockitoPlugins {
DEFAULT_PLUGINS.put(
DoNotMockEnforcer.class.getName(),
"org.mockito.internal.configuration.DefaultDoNotMockEnforcer");

MOCK_MAKER_ALIASES.add(INLINE_ALIAS);
MOCK_MAKER_ALIASES.add(PROXY_ALIAS);
MOCK_MAKER_ALIASES.add(SUBCLASS_ALIAS);
}

@Override
Expand All @@ -64,7 +71,8 @@ public <T> T getDefaultPlugin(Class<T> pluginType) {
return create(pluginType, className);
}

String getDefaultPluginClass(String classOrAlias) {
public String getDefaultPluginClass(String classOrAlias) {
// TODO: #2701 We could make this method static?
return DEFAULT_PLUGINS.get(classOrAlias);
}

Expand Down
Expand Up @@ -23,9 +23,7 @@ class PluginRegistry {
private final MockMaker mockMaker =
new PluginLoader(
pluginSwitch,
DefaultMockitoPlugins.INLINE_ALIAS,
DefaultMockitoPlugins.PROXY_ALIAS,
DefaultMockitoPlugins.SUBCLASS_ALIAS)
DefaultMockitoPlugins.MOCK_MAKER_ALIASES.toArray(new String[0]))
.loadPlugin(MockMaker.class);

private final MemberAccessor memberAccessor =
Expand Down
49 changes: 20 additions & 29 deletions src/main/java/org/mockito/internal/util/MockUtil.java
Expand Up @@ -4,14 +4,11 @@
*/
package org.mockito.internal.util;

import org.mockito.MockMakers;
import org.mockito.MockedConstruction;
import org.mockito.Mockito;
import org.mockito.exceptions.misusing.NotAMockException;
import org.mockito.internal.configuration.plugins.DefaultMockitoPlugins;
import org.mockito.internal.configuration.plugins.Plugins;
import org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker;
import org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker;
import org.mockito.internal.creation.proxy.ProxyMockMaker;
import org.mockito.internal.creation.settings.CreationSettings;
import org.mockito.internal.stubbing.InvocationContainerImpl;
import org.mockito.internal.util.reflection.LenientCopyTool;
Expand All @@ -36,6 +33,7 @@ public class MockUtil {
private static final Map<Class<? extends MockMaker>, MockMaker> mockMakers =
new ConcurrentHashMap<>(
Collections.singletonMap(defaultMockMaker.getClass(), defaultMockMaker));
private static final DefaultMockitoPlugins defaultMockitoPlugins = new DefaultMockitoPlugins();

private MockUtil() {}

Expand All @@ -44,32 +42,25 @@ private static MockMaker getMockMaker(String mockMaker) {
return defaultMockMaker;
}

// TODO: Share logic with PluginInitializer.loadImpl
String typeName;
if (DefaultMockitoPlugins.MOCK_MAKER_ALIASES.contains(mockMaker)) {
typeName = defaultMockitoPlugins.getDefaultPluginClass(mockMaker);
} else {
typeName = mockMaker;
}

Class<? extends MockMaker> type;
switch (mockMaker) {
case MockMakers.INLINE:
type = InlineByteBuddyMockMaker.class;
break;
case MockMakers.PROXY:
type = ProxyMockMaker.class;
break;
case MockMakers.SUBCLASS:
type = ByteBuddyMockMaker.class;
break;
default:
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
try {
type = loader.loadClass(mockMaker).asSubclass(MockMaker.class);
} catch (Exception e) {
throw new IllegalStateException(
"Failed to load MockMaker: " + mockMaker, e);
}
break;
}
// TODO: #2701 I doubt that it is a good idea to use the context class loader here,
// but PluginInitializer.loadImpl is using it as well,
// but DefaultMockitoPlugins.create is explicitly not using it.
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
try {
type = loader.loadClass(typeName).asSubclass(MockMaker.class);
} catch (Exception e) {
throw new IllegalStateException("Failed to load MockMaker: " + mockMaker, e);
}

return mockMakers.computeIfAbsent(
Expand Down
Expand Up @@ -259,7 +259,7 @@ public int compare(Constructor<?> constructorA, Constructor<?> constructorB) {
private int countMockableParams(Constructor<?> constructor) {
int constructorMockableParamsSize = 0;
for (Class<?> aClass : constructor.getParameterTypes()) {
// TODO: I don't really understand the reason for this check here.
// TODO: #2701 I don't really understand the reason for this check here.
// It looks like we are not actually creating any mocks for these
// parameters, but might only use mocks which are already created
// and stored in some fields.
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/org/mockito/plugins/MockMaker.java
Expand Up @@ -48,11 +48,15 @@
*
* <h3>Using the MockSettings of individual mocks</h3>
*
* <p>If you want to use your {@code AwesomeMockMaker} only for a specific mock,
* <p>If you want to use a {@code MockMaker} only for a specific mock,
* you can specify it using {@link MockSettings#mockMaker(String)}.</p>
* <pre>
* // Use a mockmaker shipping with Mockito
* Object mock = Mockito.mock(Object.class, Mockito.withSettings()
* .mockMaker(AwesomeMockMaker.class));
* .mockMaker(MockMakers.INLINE));
* // Or load a mockmaker using a fully qualified class name
* Object mock = Mockito.mock(Object.class, Mockito.withSettings()
* .mockMaker("org.awesome.mockito.AwesomeMockMaker"));
* </pre>
*
* @see org.mockito.mock.MockCreationSettings
Expand Down

0 comments on commit cac5ffa

Please sign in to comment.