mockit.internal.expectations.invocation.DelegatedResult Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmockit Show documentation
Show all versions of jmockit Show documentation
JMockit is a Java toolkit for automated developer testing.
It contains APIs for the creation of the objects to be tested, for mocking dependencies, and for faking external
APIs; JUnit (4 & 5) and TestNG test runners are supported.
It also contains an advanced code coverage tool.
The newest version!
/*
* Copyright (c) 2006 JMockit developers
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.expectations.invocation;
import static mockit.internal.reflection.MethodReflection.JAVA_LANG;
import static mockit.internal.reflection.MethodReflection.findNonPrivateHandlerMethod;
import static mockit.internal.reflection.MethodReflection.invoke;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.lang.reflect.Method;
import java.util.concurrent.locks.ReentrantLock;
import mockit.Delegate;
import mockit.Invocation;
import mockit.asm.types.JavaType;
import mockit.internal.expectations.RecordAndReplayExecution;
import mockit.internal.reflection.ParameterReflection;
import mockit.internal.state.TestRun;
import mockit.internal.util.MethodFormatter;
import mockit.internal.util.TypeDescriptor;
final class DelegatedResult extends InvocationResult {
private static final Object[] NO_ARGS = {};
@NonNull
private final ExpectedInvocation recordedInvocation;
@NonNull
private final Object targetObject;
@NonNull
private final Method methodToInvoke;
@NonNull
private final Class> targetReturnType;
private final boolean hasInvocationParameter;
private final int numberOfRegularParameters;
DelegatedResult(@NonNull ExpectedInvocation recordedInvocation, @NonNull Delegate> delegate) {
this.recordedInvocation = recordedInvocation;
targetObject = delegate;
methodToInvoke = findNonPrivateHandlerMethod(delegate);
JavaType returnType = JavaType.getReturnType(recordedInvocation.getMethodNameAndDescription());
targetReturnType = TypeDescriptor.getClassForType(returnType);
Class>[] parameters = methodToInvoke.getParameterTypes();
int n = parameters.length;
hasInvocationParameter = n > 0 && parameters[0] == Invocation.class;
numberOfRegularParameters = hasInvocationParameter ? n - 1 : n;
}
@Nullable
@Override
Object produceResult(@Nullable Object invokedObject, @NonNull ExpectedInvocation invocation,
@NonNull InvocationConstraints constraints, @NonNull Object[] args) {
Object[] delegateArgs = numberOfRegularParameters == 0 ? NO_ARGS : args;
return hasInvocationParameter
? invokeMethodWithContext(invokedObject, invocation, constraints, args, delegateArgs)
: executeMethodToInvoke(delegateArgs);
}
@Nullable
private Object invokeMethodWithContext(@Nullable Object mockOrRealObject,
@NonNull ExpectedInvocation expectedInvocation, @NonNull InvocationConstraints constraints,
@NonNull Object[] invokedArgs, @NonNull Object[] delegateArgs) {
Invocation delegateInvocation = new DelegateInvocation(mockOrRealObject, invokedArgs, expectedInvocation,
constraints);
Object[] delegateArgsWithInvocation = ParameterReflection.argumentsWithExtraFirstValue(delegateArgs,
delegateInvocation);
Object result = executeMethodToInvoke(delegateArgsWithInvocation);
return expectedInvocation.isConstructor() && TestRun.getExecutingTest().isProceedingIntoRealImplementation()
? Void.class
: result;
}
@Nullable
private Object executeMethodToInvoke(@NonNull Object[] args) {
ReentrantLock reentrantLock = RecordAndReplayExecution.RECORD_OR_REPLAY_LOCK;
if (!reentrantLock.isHeldByCurrentThread()) {
return executeTargetMethod(args);
}
reentrantLock.unlock();
try {
return executeTargetMethod(args);
} finally {
// noinspection LockAcquiredButNotSafelyReleased
reentrantLock.lock();
}
}
@Nullable
private Object executeTargetMethod(@NonNull Object[] args) {
Object returnValue = invoke(targetObject, methodToInvoke, args);
Class> fromReturnType = methodToInvoke.getReturnType();
if (returnValue == null || targetReturnType.isInstance(returnValue)) {
if (fromReturnType == void.class && fromReturnType != targetReturnType && targetReturnType.isPrimitive()) {
String returnTypeName = JAVA_LANG.matcher(targetReturnType.getName()).replaceAll("");
MethodFormatter methodDesc = new MethodFormatter(recordedInvocation.getClassDesc(),
recordedInvocation.getMethodNameAndDescription());
String msg = "void return type incompatible with return type " + returnTypeName + " of " + methodDesc;
throw new IllegalArgumentException(msg);
}
return returnValue;
}
ReturnTypeConversion typeConversion = new ReturnTypeConversion(recordedInvocation, targetReturnType,
returnValue);
return typeConversion.getConvertedValue();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy