Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2006-2013 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import java.lang.reflect.*;
import java.util.concurrent.*;
import mockit.internal.util.*;
/**
* A context object representing the current invocation to a mocked method/constructor, to be passed as the
* first parameter of the corresponding mock method implementation.
*
* With the Expectations & Verifications API, this parameter can appear in mock methods implemented in
* {@link Delegate} classes or in validation objects assigned to the
* {@link Invocations#forEachInvocation forEachInvocation} field.
* With the Mockups API, it can appear in {@link Mock @Mock} methods.
*
* Sample tests:
* DelegateInvocationTest,
* MockInvocationTest
*
* @see #getInvokedInstance()
* @see #getInvokedArguments()
* @see #getInvocationCount()
* @see #getInvocationIndex()
* @see #getMinInvocations()
* @see #getMaxInvocations()
* @see #setMinInvocations(int)
* @see #setMaxInvocations(int)
* @see #proceed(Object...)
*/
public class Invocation
{
private final Object invokedInstance;
private final Object[] invokedArguments;
private final int invocationCount;
private int minInvocations;
private int maxInvocations;
/**
* For internal use only.
*/
protected Invocation(
Object invokedInstance, Object[] invokedArguments, int invocationCount, int minInvocations, int maxInvocations)
{
this.invokedInstance = invokedInstance;
this.invokedArguments = invokedArguments;
this.invocationCount = invocationCount;
this.minInvocations = minInvocations;
this.maxInvocations = maxInvocations;
}
/**
* Returns the instance on which the current invocation was made, or {@code null} for a {@code static} method
* invocation.
*/
public final T getInvokedInstance()
{
//noinspection unchecked
return (T) invokedInstance;
}
/**
* Returns the actual argument values passed in the invocation to the mocked method/constructor.
*/
public final Object[] getInvokedArguments() { return invokedArguments; }
/**
* Returns the current invocation count. The first invocation starts at 1 (one).
*/
public final int getInvocationCount() { return invocationCount; }
/**
* Returns the index for the current invocation. The first invocation starts at 0 (zero).
* Note that this is equivalent to {@link #getInvocationCount()} - 1.
*/
public final int getInvocationIndex() { return invocationCount - 1; }
/**
* Returns the current value of the minimum invocation count associated with the matching expectation or mock method.
*
* For an expectation, this call will return the value specified through the
* {@linkplain Invocations#times times} or {@linkplain Invocations#minTimes minTimes} field, if that was the case;
* if not, the value will be {@code 0} for a non-strict expectation and {@code 1} for a strict expectation.
* For a {@code @Mock} method, it will return the value specified for the {@linkplain Mock#invocations invocations}
* or {@linkplain Mock#minInvocations minInvocations} attribute, or {@code 0} if none.
*/
public final int getMinInvocations() { return minInvocations; }
/**
* Sets the current value of the minimum invocation count for the matching expectation or mock method.
*
* For an expectation, this call can be used to override the value set on the {@linkplain Invocations#times times} or
* {@linkplain Invocations#minTimes minTimes} field.
* For a {@code @Mock} method, it would override the value specified in the
* {@linkplain Mock#invocations invocations} or {@linkplain Mock#minInvocations minInvocations} attribute.
*/
public final void setMinInvocations(int minInvocations)
{
this.minInvocations = minInvocations;
onChange();
}
/**
* Returns the current value of the maximum invocation count for the matching expectation or mock method ({@code -1}
* indicates that it's unlimited).
*
* For an expectation, this call will return the value specified through the
* {@linkplain Invocations#times times} or {@linkplain Invocations#maxTimes maxTimes} field, if that was the case;
* if not, the value will be {@code -1} for a non-strict expectation and {@code 1} for a strict expectation.
* For a {@code @Mock} method, it will return the value specified for the {@linkplain Mock#invocations invocations}
* or {@linkplain Mock#maxInvocations maxInvocations} attribute, or {@code -1} if none.
*/
public final int getMaxInvocations() { return maxInvocations; }
/**
* Sets the current value of the maximum invocation count for the matching expectation or mock method.
* The value of {@code -1} implies no upper limit.
*
* For an expectation, this call can be used to override the value set on the {@linkplain Invocations#times times} or
* {@linkplain Invocations#maxTimes maxTimes} field.
* For a {@code @Mock} method, it would override the value specified in the
* {@linkplain Mock#invocations invocations} or {@linkplain Mock#maxInvocations maxInvocations} attribute.
*/
public final void setMaxInvocations(int maxInvocations)
{
this.maxInvocations = maxInvocations;
onChange();
}
private void onChange()
{
// Ugly, but prevents this method from appearing in API documentation, which would occur if it was *protected*.
//noinspection InstanceofThis
if (this instanceof Runnable) {
((Runnable) this).run();
}
}
/**
* Allows execution to proceed into the real implementation of the mocked method/constructor.
*
* In the case of a mocked method, the real implementation is executed with the argument values originally received
* or explicitly given as replacement.
* Whatever comes out of that call (either a return value or a thrown exception/error, even if it is a
* checked exception) becomes the result of the current invocation to the mock method.
*
* In the case of a mocked constructor, the real constructor implementation code which comes after the necessary call
* to "super" is executed, using the original argument values; replacement arguments are not supported.
* If the execution of said code throws an exception or error, it is propagated out to the caller of the mocked
* constructor (even in the case of a checked exception).
* Contrary to proceeding into a mocked method, it's not possible to actually execute test code inside the delegate
* method after proceeding into the real constructor, nor to proceed into it more than once.
*
* @param replacementArguments the argument values to be passed to the real method, as replacement for the values
* received by the mock method; if those received values should be passed without
* replacement, then this method should be called with no values
* @param the return type of the mocked method
*
* @return the same value returned by the real method, if any
*
* @throws UnsupportedOperationException if attempting to proceed into a mocked method which does not belong to an
* {@linkplain Injectable injectable mocked type} nor to a {@linkplain Expectations#Expectations(Object...) dynamic
* partially mocked type}, into a {@code native} method, or into a mocked constructor while passing replacement
* arguments
*/
public final T proceed(Object... replacementArguments)
{
boolean withArgs = replacementArguments != null && replacementArguments.length > 0;
Method realMethod = getRealMethod();
if (realMethod == null) {
if (withArgs) {
throw new UnsupportedOperationException("Cannot replace arguments when proceeding into constructor");
}
return null;
}
Object[] actualArgs = invokedArguments;
if (withArgs) {
actualArgs =
realMethod.isVarArgs() ? createArgumentsArrayWithVarargs(replacementArguments) : replacementArguments;
}
return MethodReflection.invoke(invokedInstance, realMethod, actualArgs);
}
private Object[] createArgumentsArrayWithVarargs(Object[] replacementArguments)
{
int n = invokedArguments.length;
int m = n - 1;
Object[] actualArgs = new Object[n];
System.arraycopy(replacementArguments, 0, actualArgs, 0, m);
Object[] replacementVarargs = new Object[replacementArguments.length - m];
System.arraycopy(replacementArguments, m, replacementVarargs, 0, replacementVarargs.length);
actualArgs[m] = replacementVarargs;
return actualArgs;
}
private Method getRealMethod()
{
// Ugly, but prevents this method from appearing in API documentation, which would occur if it was *protected*.
try {
//noinspection unchecked
return ((Callable) this).call();
}
catch (RuntimeException e) { throw e; }
catch (Exception ignore) { return null; }
}
}