Skip to content

Commit

Permalink
[ci maven-central-release] Merge pull request #1974 from mockito/impr…
Browse files Browse the repository at this point in the history
…ove-error-message

Fixes #1855 and #939: improve error message when the inline mock maker cannot be used.
  • Loading branch information
raphw committed Jul 18, 2020
2 parents cbabc53 + 12ba593 commit 6b09281
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
Expand Up @@ -58,7 +58,7 @@ private List<AutoCloseable> processInjectMocks(
List<AutoCloseable> closeables = new ArrayList<>();
Class<?> classContext = clazz;
while (classContext != Object.class) {
closeables.add(injectMocks(testInstance));
closeables.add(injectCloseableMocks(testInstance));
classContext = classContext.getSuperclass();
}
return closeables;
Expand All @@ -79,6 +79,20 @@ private List<AutoCloseable> processIndependentAnnotations(
return closeables;
}

/**
* Required by PowerMockito and retained to avoid API breakage despite being internal API.
*
* @deprecated Use {@link InjectingAnnotationEngine#injectCloseableMocks(Object)}.
*/
@Deprecated
public void injectMocks(Object testClassInstance) {
try {
injectCloseableMocks(testClassInstance).close();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}

/**
* Initializes mock/spies dependencies for objects annotated with
* &#064;InjectMocks for given testClassInstance.
Expand All @@ -88,7 +102,7 @@ private List<AutoCloseable> processIndependentAnnotations(
* @param testClassInstance
* Test class, usually <code>this</code>
*/
private AutoCloseable injectMocks(final Object testClassInstance) {
private AutoCloseable injectCloseableMocks(final Object testClassInstance) {
Class<?> clazz = testClassInstance.getClass();
Set<Field> mockDependentFields = new HashSet<Field>();
Set<Object> mocks = newMockSafeHashSet();
Expand Down
Expand Up @@ -4,24 +4,20 @@
*/
package org.mockito.internal.creation.bytebuddy;

import static org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.EXCLUDES;
import static org.mockito.internal.util.StringUtil.join;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

import javax.tools.ToolProvider;

import net.bytebuddy.agent.ByteBuddyAgent;
import org.mockito.Incubating;
import org.mockito.creation.instance.Instantiator;
Expand All @@ -35,6 +31,9 @@
import org.mockito.mock.MockCreationSettings;
import org.mockito.plugins.InlineMockMaker;

import static org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator.*;
import static org.mockito.internal.util.StringUtil.*;

/**
* Agent and subclass based mock maker.
* <p>
Expand Down Expand Up @@ -191,12 +190,34 @@ public class InlineByteBuddyMockMaker implements ClassCreatingMockMaker, InlineM

public InlineByteBuddyMockMaker() {
if (INITIALIZATION_ERROR != null) {
String detail;
if (System.getProperty("java.specification.vendor", "")
.toLowerCase()
.contains("android")) {
detail =
"It appears as if you are trying to run this mock maker on Android which does not support the instrumentation API.";
} else {
try {
if (Class.forName("javax.tools.ToolProvider")
.getMethod("getSystemJavaCompiler")
.invoke(null)
== null) {
detail =
"It appears as if you are running on a JRE. Either install a JDK or add JNA to the class path.";
} else {
detail =
"It appears as if your JDK does not supply a working agent attachment mechanism.";
}
} catch (Throwable ignored) {
detail =
"It appears as if you are running an incomplete JVM installation that might not support all tooling APIs";
}
}
throw new MockitoInitializationException(
join(
"Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)",
ToolProvider.getSystemJavaCompiler() == null
? "Are you running a JRE instead of a JDK? The inline mock maker needs to be run on a JDK.\n"
: "",
"Could not initialize inline Byte Buddy mock maker.",
"",
detail,
Platform.describe()),
INITIALIZATION_ERROR);
}
Expand Down Expand Up @@ -384,11 +405,12 @@ public <T> StaticMockControl<T> createStaticMock(
+ "to avoid infinitive loops within Mockito's implementation of static mock handling");
} else if (type == Thread.class
|| type == System.class
|| type == Arrays.class
|| ClassLoader.class.isAssignableFrom(type)) {
throw new MockitoException(
"It is not possible to mock static methods of "
+ type.getTypeName()
+ "to avoid interfering with the class loading mechanism");
+ " to avoid interfering with class loading what leads to infinite loops");
}

bytecodeGenerator.mockClassStatic(type);
Expand Down

0 comments on commit 6b09281

Please sign in to comment.