mockit.Invocations Maven / Gradle / Ivy
Show all versions of jmockit Show documentation
/*
* Copyright (c) 2006 JMockit developers
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import mockit.internal.expectations.TestOnlyPhase;
import mockit.internal.expectations.argumentMatching.AlwaysTrueMatcher;
import mockit.internal.expectations.argumentMatching.ArgumentMatcher;
import mockit.internal.expectations.argumentMatching.CaptureMatcher;
import mockit.internal.expectations.argumentMatching.ClassMatcher;
import mockit.internal.expectations.argumentMatching.HamcrestAdapter;
import mockit.internal.expectations.argumentMatching.InequalityMatcher;
import mockit.internal.expectations.argumentMatching.LenientEqualityMatcher;
import mockit.internal.expectations.argumentMatching.NonNullityMatcher;
import mockit.internal.expectations.argumentMatching.NullityMatcher;
import mockit.internal.expectations.argumentMatching.NumericEqualityMatcher;
import mockit.internal.expectations.argumentMatching.PatternMatcher;
import mockit.internal.expectations.argumentMatching.ReflectiveMatcher;
import mockit.internal.expectations.argumentMatching.SamenessMatcher;
import mockit.internal.expectations.argumentMatching.StringContainmentMatcher;
import mockit.internal.expectations.argumentMatching.StringPrefixMatcher;
import mockit.internal.expectations.argumentMatching.StringSuffixMatcher;
import mockit.internal.startup.Startup;
import mockit.internal.util.DefaultValues;
import org.checkerframework.checker.index.qual.NonNegative;
import org.hamcrest.Matcher;
/**
* Provides common API for use inside {@linkplain Expectations expectation} and {@linkplain Verifications verification}
* blocks.
*/
@SuppressWarnings("ClassWithTooManyFields")
class Invocations {
static {
Startup.verifyInitialization();
}
/**
* Matches any Object
reference received by a parameter of a reference type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* Notice the use of this field will usually require a cast to the specific parameter type. However, if there is any
* other parameter for which an argument matching constraint is specified, passing the null
reference
* instead will have the same effect.
*
* To match an entire varargs parameter of element type V
(ie, all arguments in the array),
* cast it to the parameter type: "(V[]) any
".
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyShort
* @see #anyString
* @see Tutorial
*/
@Nullable
protected final Object any = null;
/**
* Matches any String
value received by a parameter of this type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyShort
* @see #any
* @see Tutorial
*/
// This is intentional: the empty string causes the compiler to not generate a field read, while the null reference
// is inconvenient with
// the invoke(...) methods:
@NonNull
protected final String anyString = new String();
/**
* Matches any long
or Long
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyShort
* @see #anyString
* @see #any
* @see Tutorial
*/
@NonNull
protected final Long anyLong = 0L;
/**
* Matches any int
or Integer
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyLong
* @see #anyShort
* @see #anyString
* @see #any
* @see Tutorial
*/
@NonNull
protected final Integer anyInt = 0;
/**
* Matches any short
or Short
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyString
* @see #any
* @see Tutorial
*/
@NonNull
protected final Short anyShort = 0;
/**
* Matches any byte
or Byte
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyShort
* @see #anyString
* @see #any
* @see Tutorial
*/
@NonNull
protected final Byte anyByte = 0;
/**
* Matches any boolean
or Boolean
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyShort
* @see #anyString
* @see #any
* @see Tutorial
*/
@NonNull
protected final Boolean anyBoolean = false;
/**
* Matches any char
or Character
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyByte
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyShort
* @see #anyString
* @see #any
* @see Tutorial
*/
@NonNull
protected final Character anyChar = '\0';
/**
* Matches any double
or Double
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyShort
* @see #anyString
* @see #any
* @see Tutorial
*/
@NonNull
protected final Double anyDouble = 0.0;
/**
* Matches any float
or Float
value received by a parameter of that type.
*
* This field can only be used as the argument value at the proper parameter position in a method/constructor
* invocation, when recording or verifying an expectation; it cannot be used anywhere else.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyInt
* @see #anyLong
* @see #anyString
* @see #anyShort
* @see #any
* @see Tutorial
*/
@NonNull
protected final Float anyFloat = 0.0F;
/**
* A non-negative value assigned to this field will be taken as the exact number of times that invocations matching
* the current expectation should occur during replay.
*
* @see #minTimes
* @see #maxTimes
* @see Tutorial
*/
@NonNegative
protected int times;
/**
* A positive value assigned to this field will be taken as the minimum number of times that invocations matching
* the current expectation should occur during replay. Zero or a negative value means there is no
* lower limit.
*
* If not specified, the default value of 1
(one) is used.
*
* The maximum number of times is automatically adjusted to allow any number of invocations. Both
* minTimes
and maxTimes
can be specified for the same expectation, provided
* minTimes
is assigned first.
*
* @see #times
* @see #maxTimes
* @see Tutorial
*/
protected int minTimes;
/**
* A non-negative value assigned to this field will be taken as the maximum number of times that invocations
* matching the current expectation should occur during replay. A negative value implies there is no upper
* limit (the default).
*
* Both minTimes
and maxTimes
can be specified for the same expectation, provided
* minTimes
is assigned first.
*
* @see #times
* @see #minTimes
* @see Tutorial
*/
protected int maxTimes;
/** The current phase. */
@SuppressWarnings("NullableProblems")
@NonNull
TestOnlyPhase currentPhase;
/**
* Applies a Hamcrest argument matcher for a parameter in the current expectation.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @param
* the generic type
* @param argumentMatcher
* any org.hamcrest.Matcher object
*
* @return the value recorded inside the given Hamcrest matcher, or null if there is no such value to be
* found
*
* @see #with(Delegate) Use {@linkplain #withCapture(List) argument capturing} or {@link #with(Delegate)} instead.
*/
@Nullable
protected final T withArgThat(@NonNull Matcher super T> argumentMatcher) {
HamcrestAdapter matcher = new HamcrestAdapter(argumentMatcher);
addMatcher(matcher);
@SuppressWarnings("unchecked")
T argValue = (T) matcher.getInnerValue();
return argValue;
}
/**
* Applies a custom argument matcher for a parameter in the current expectation.
*
* The class of the given delegate object should define a single non-private
delegate method
* (plus any number of helper private
methods). The name of the delegate method doesn't matter, but it
* must have a single parameter capable of receiving the relevant argument values.
*
* The return type of the delegate method should be boolean
or void
. In the first case, a
* return value of true
will indicate a successful match for the actual invocation argument at replay
* time, while a return of false
will fail to match the invocation. In the case of a void
* return type, the actual invocation argument should be validated through a suitable JUnit/TestNG assertion.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @param
* the generic type
* @param objectWithDelegateMethod
* an instance of a class defining a single non-private
delegate method
*
* @return the default primitive value corresponding to T
if it's a primitive wrapper type, or
* null
otherwise
*
* @see #withArgThat(org.hamcrest.Matcher)
* @see Tutorial
*/
@Nullable
protected final T with(@NonNull Delegate super T> objectWithDelegateMethod) {
addMatcher(new ReflectiveMatcher(objectWithDelegateMethod));
Class> delegateClass = objectWithDelegateMethod.getClass();
Type[] genericInterfaces = delegateClass.getGenericInterfaces();
while (genericInterfaces.length == 0) {
delegateClass = delegateClass.getSuperclass();
genericInterfaces = delegateClass.getGenericInterfaces();
}
Type typeFromDelegateImplementationClass = genericInterfaces[0];
if (!(typeFromDelegateImplementationClass instanceof ParameterizedType)) {
return null;
}
Type parameterType = ((ParameterizedType) typeFromDelegateImplementationClass).getActualTypeArguments()[0];
return DefaultValues.computeForWrapperType(parameterType);
}
/**
* Adds the matcher.
*
* @param matcher
* the matcher
*/
private void addMatcher(@NonNull ArgumentMatcher> matcher) {
currentPhase.addArgMatcher(matcher);
}
/**
* Same as {@link #withEqual(Object)}, but matching any argument value of the appropriate type (null
* included).
*
* Consider using instead the "anyXyz" field appropriate to the parameter type: {@link #anyBoolean},
* {@link #anyByte}, {@link #anyChar}, {@link #anyDouble}, {@link #anyFloat}, {@link #anyInt}, {@link #anyLong},
* {@link #anyShort}, {@link #anyString}, or {@link #any} for other reference types.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @param
* the generic type
* @param arg
* an arbitrary value which will match any argument value in the replay phase
*
* @return the input argument
*
* @see Tutorial
*/
@NonNull
protected final T withAny(@NonNull T arg) {
ArgumentMatcher> matcher;
if (arg instanceof String) {
matcher = AlwaysTrueMatcher.ANY_STRING;
} else if (arg instanceof Integer) {
matcher = AlwaysTrueMatcher.ANY_INT;
} else if (arg instanceof Boolean) {
matcher = AlwaysTrueMatcher.ANY_BOOLEAN;
} else if (arg instanceof Character) {
matcher = AlwaysTrueMatcher.ANY_CHAR;
} else if (arg instanceof Double) {
matcher = AlwaysTrueMatcher.ANY_DOUBLE;
} else if (arg instanceof Float) {
matcher = AlwaysTrueMatcher.ANY_FLOAT;
} else if (arg instanceof Long) {
matcher = AlwaysTrueMatcher.ANY_LONG;
} else if (arg instanceof Byte) {
matcher = AlwaysTrueMatcher.ANY_BYTE;
} else if (arg instanceof Short) {
matcher = AlwaysTrueMatcher.ANY_SHORT;
} else {
matcher = AlwaysTrueMatcher.ANY_VALUE;
}
addMatcher(matcher);
return arg;
}
/**
* Captures the argument value passed into the associated expectation parameter, for each invocation that matches
* the expectation when the tested code is exercised. As each such value is captured, it gets added to the given
* list so that it can be inspected later. Apart from capturing received argument values, this method has the same
* effect as the {@link #any} argument matcher.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* @param
* the generic type
* @param valueHolderForMultipleInvocations
* list into which the arguments received by matching invocations will be added
*
* @return the default value for type T
*
* @see Verifications#withCapture()
* @see Verifications#withCapture(Object)
* @see Tutorial
*/
@Nullable
protected final T withCapture(@NonNull List valueHolderForMultipleInvocations) {
addMatcher(new CaptureMatcher<>(valueHolderForMultipleInvocations));
return null;
}
/**
* When passed as argument for an expectation, creates a new matcher that will check if the given value is
* {@link Object#equals(Object) equal} to the corresponding argument received by a matching invocation.
*
* The matcher is added to the end of the list of argument matchers for the invocation being recorded/verified. It
* cannot be reused for a different parameter.
*
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's not necessary to also use matchers for the other parameters. So, it's valid to
* mix the use of matchers with given values. Any arguments given as literals, local variables, or fields will be
* implicitly matched as if withEqual(value)
had been used. In the special case of a varargs method,
* however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
* the varargs array, then a matcher must be used for every other parameter and varargs element.
*
* Usually, this particular method should not be used. Instead, simply pass the desired argument value
* directly, without any matcher. Only when specifying values for a varargs method it's useful, and even
* then only when some other argument matcher is also used.
*
* @param
* the generic type
* @param arg
* the expected argument value
*
* @return the given argument
*
* @see Tutorial
*/
@NonNull
protected final T withEqual(@NonNull T arg) {
Map