/*
* Copyright (c) 2006 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.*;
import java.util.regex.*;
import javax.annotation.*;
import mockit.internal.expectations.*;
import mockit.internal.expectations.argumentMatching.*;
import mockit.internal.startup.*;
import mockit.internal.util.*;
import org.hamcrest.Matcher;
/**
* Provides common API for use inside {@linkplain Expectations expectation} and {@linkplain Verifications verification}
* blocks.
*/
@SuppressWarnings("ClassWithTooManyFields")
abstract class Invocations
{
static { Startup.verifyInitialization(); }
/**
* Matches any {@code Object} reference received by a parameter of a reference type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
* <p/>
* 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
* {@code null} reference instead will have the same effect.
* <p/>
* To match an entire <em>varargs</em> parameter of element type {@code V} (ie, all arguments in the array), cast it
* to the parameter type: "{@code (V[]) any}".
*
* @see #anyBoolean
* @see #anyByte
* @see #anyChar
* @see #anyDouble
* @see #anyFloat
* @see #anyInt
* @see #anyLong
* @see #anyShort
* @see #anyString
* @see <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Object any = null;
/**
* Matches any {@code String} value received by a parameter of this type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
// 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:
protected final String anyString = new String();
/**
* Matches any {@code long} or {@code Long} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Long anyLong = 0L;
/**
* Matches any {@code int} or {@code Integer} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Integer anyInt = 0;
/**
* Matches any {@code short} or {@code Short} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Short anyShort = 0;
/**
* Matches any {@code byte} or {@code Byte} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Byte anyByte = 0;
/**
* Matches any {@code boolean} or {@code Boolean} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Boolean anyBoolean = false;
/**
* Matches any {@code char} or {@code Character} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Character anyChar = '\0';
/**
* Matches any {@code double} or {@code Double} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
protected final Double anyDouble = 0.0;
/**
* Matches any {@code float} or {@code Float} value received by a parameter of that type.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> 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 <a href="http://jmockit.org/tutorial/Mocking.html#matcherFields">Tutorial</a>
*/
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 <a href="http://jmockit.org/tutorial/Mocking.html#constraints">Tutorial</a>
*/
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.
* <em>Zero</em> or a <em>negative</em> value means there is no lower limit, but only when applied to an expectation
* recorded in a test setup method, to a strict expectation, or to a full verification.
* <p/>
* If not specified, the default value of {@code 1} (one) is used.
* <p/>
* The <em>maximum</em> number of times is automatically adjusted to allow any number of invocations.
* Both {@code minTimes} and {@code maxTimes} can be specified for the same expectation, as long as {@code minTimes}
* is assigned first.
*
* @see #times
* @see #maxTimes
* @see <a href="http://jmockit.org/tutorial/Mocking.html#constraints">Tutorial</a>
*/
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 <em>negative</em> value implies there is no upper limit.
* <p/>
* If not specified, there is no upper limit by default, except in the case of a strict expectation, where the
* default is {@code 1} (one).
* <p/>
* Both {@code minTimes} and {@code maxTimes} can be specified for the same expectation, as long as {@code minTimes}
* is assigned first.
*
* @see #times
* @see #minTimes
* @see <a href="http://jmockit.org/tutorial/Mocking.html#constraints">Tutorial</a>
*/
protected int maxTimes;
@Nullable abstract TestOnlyPhase getCurrentPhase();
// Methods for argument matching ///////////////////////////////////////////////////////////////////////////////////
/**
* Applies a <em>Hamcrest</em> argument matcher for a parameter in the current expectation.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param argumentMatcher any {@code org.hamcrest.Matcher} object
*
* @return the value recorded inside the given Hamcrest matcher, or {@code null} if there is no such value to be
* found
*
* @see #with(Delegate)
*/
protected final <T> T withArgThat(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.
* <p/>
* The class of the given delegate object should define a single non-<code>private</code> <em>delegate</em> method
* (plus any number of helper {@code 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.
* <p/>
* The return type of the delegate method should be {@code boolean} or {@code void}.
* In the first case, a return value of {@code true} will indicate a successful match for the actual invocation
* argument at replay time, while a return of {@code false} will fail to match the invocation.
* In the case of a {@code void} return type, the actual invocation argument should be validated through a suitable
* JUnit/TestNG assertion.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param objectWithDelegateMethod an instance of a class defining a single non-<code>private</code> delegate method
*
* @return the default primitive value corresponding to {@code T} if it's a primitive wrapper type, or {@code null}
* otherwise
*
* @see #withArgThat(org.hamcrest.Matcher)
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T with(Delegate<? super T> objectWithDelegateMethod)
{
Class<?> delegateClass = objectWithDelegateMethod.getClass();
Type[] genericInterfaces = delegateClass.getGenericInterfaces();
while (genericInterfaces.length == 0) {
delegateClass = delegateClass.getSuperclass();
genericInterfaces = delegateClass.getGenericInterfaces();
}
if (!(genericInterfaces[0] instanceof ParameterizedType)) {
throw new IllegalArgumentException("Delegate class lacks the parameter type");
}
ParameterizedType type = (ParameterizedType) genericInterfaces[0];
Type parameterType = type.getActualTypeArguments()[0];
addMatcher(new ReflectiveMatcher(objectWithDelegateMethod));
return DefaultValues.computeForWrapperType(parameterType);
}
private void addMatcher(@Nonnull ArgumentMatcher<?> matcher)
{
TestOnlyPhase currentPhase = getCurrentPhase();
if (currentPhase != null) {
currentPhase.addArgMatcher(matcher);
}
}
/**
* Same as {@link #withEqual(Object)}, but matching any argument value of the appropriate type ({@code null}
* included).
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param arg an arbitrary value which will match any argument value in the replay phase
*
* @return the input argument
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withAny(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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param valueHolderForMultipleInvocations list into which the arguments received by matching invocations will be
* added
*
* @return the default value for type {@code T}
*
* @see Verifications#withCapture()
* @see Verifications#withCapture(Object)
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withCapture">Tutorial</a>
*/
protected final <T> T withCapture(List<T> valueHolderForMultipleInvocations)
{
addMatcher(new CaptureMatcher<T>(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.
* <p/>
* 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.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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
* {@code 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 <em>must</em> be used for every other
* parameter and varargs element.
* <p/>
* Usually, this particular method should <em>not</em> be used.
* Instead, simply pass the desired argument value directly, without any matcher.
* Only when specifying values for a <em>varargs</em> method it's useful, and even then only when some other argument
* matcher is also used.
*
* @param arg the expected argument value
*
* @return the given argument
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withEqual(T arg)
{
TestOnlyPhase currentPhase = getCurrentPhase();
if (currentPhase != null) {
Map<Object, Object> instanceMap = currentPhase.getInstanceMap();
addMatcher(new LenientEqualityMatcher(arg, instanceMap));
}
return arg;
}
/**
* Same as {@link #withEqual(Object)}, but checking that a numeric invocation argument in the replay phase is
* sufficiently close to the given value.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param value the center value for range comparison
* @param delta the tolerance around the center value, for a range of [value - delta, value + delta]
*
* @return the given {@code value}
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final double withEqual(double value, double delta)
{
addMatcher(new NumericEqualityMatcher(value, delta));
return value;
}
/**
* Same as {@link #withEqual(Object)}, but checking that a numeric invocation argument in the replay phase is
* sufficiently close to the given value.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param value the center value for range comparison
* @param delta the tolerance around the center value, for a range of [value - delta, value + delta]
*
* @return the given {@code value}
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final float withEqual(float value, double delta)
{
addMatcher(new NumericEqualityMatcher(value, delta));
return value;
}
/**
* Same as {@link #withEqual(Object)}, but checking that an invocation argument in the replay phase is an instance of
* the same class as the given object.
* <p/>
* Equivalent to a <code>withInstanceOf(object.getClass())</code> call, except that it returns {@code object} instead
* of {@code null}.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param object an instance of the desired class
*
* @return the given instance
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withInstanceLike(T object)
{
addMatcher(ClassMatcher.create(object.getClass()));
return object;
}
/**
* Same as {@link #withEqual(Object)}, but checking that an invocation argument in the replay phase is an instance of
* the given class.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param argClass the desired class
*
* @return always {@code null}; if you need a specific return value, use {@link #withInstanceLike(Object)}
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withInstanceOf(Class<T> argClass)
{
addMatcher(ClassMatcher.create(argClass));
return null;
}
/**
* Same as {@link #withEqual(Object)}, but checking that the invocation argument in the replay phase is different
* from the given value.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param arg an arbitrary value, but different from the ones expected to occur during replay
*
* @return the given argument value
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withNotEqual(T arg)
{
addMatcher(new InequalityMatcher(arg));
return arg;
}
/**
* Same as {@link #withEqual(Object)}, but checking that an invocation argument in the replay phase is {@code null}.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @return always {@code null}
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withNull()
{
addMatcher(NullityMatcher.INSTANCE);
return null;
}
/**
* Same as {@link #withEqual(Object)}, but checking that an invocation argument in the replay phase is not
* {@code null}.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @return always {@code null}
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withNotNull()
{
addMatcher(NonNullityMatcher.INSTANCE);
return null;
}
/**
* Same as {@link #withEqual(Object)}, but checking that an invocation argument in the replay phase is the exact same
* instance as the one in the recorded/verified invocation.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param object the desired instance
* @return the given object
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T> T withSameInstance(T object)
{
addMatcher(new SamenessMatcher(object));
return object;
}
// Text-related matchers ///////////////////////////////////////////////////////////////////////////////////////////
/**
* Same as {@link #withEqual(Object)}, but checking that a textual invocation argument in the replay phase contains
* the given text as a substring.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param text an arbitrary non-null textual value
*
* @return the given text
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T extends CharSequence> T withSubstring(T text)
{
addMatcher(new StringContainmentMatcher(text));
return text;
}
/**
* Same as {@link #withEqual(Object)}, but checking that a textual invocation argument in the replay phase starts
* with the given text.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param text an arbitrary non-null textual value
*
* @return the given text
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T extends CharSequence> T withPrefix(T text)
{
addMatcher(new StringPrefixMatcher(text));
return text;
}
/**
* Same as {@link #withEqual(Object)}, but checking that a textual invocation argument in the replay phase ends with
* the given text.
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param text an arbitrary non-null textual value
*
* @return the given text
*
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T extends CharSequence> T withSuffix(T text)
{
addMatcher(new StringSuffixMatcher(text));
return text;
}
/**
* Same as {@link #withEqual(Object)}, but checking that a textual invocation argument in the replay phase matches
* the given {@link Pattern regular expression}.
* <p/>
* Note that this can be used for any string comparison, including case insensitive ones (with {@code "(?i)"} in the
* regex).
* <p/>
* When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
* method/constructor, it's <em>not</em> 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 <em>must</em> be used for every other
* parameter and varargs element.
*
* @param regex an arbitrary (non-null) regular expression against which textual argument values will be matched
*
* @return the given regex
*
* @see Pattern#compile(String, int)
* @see <a href="http://jmockit.org/tutorial/Mocking.html#withMethods">Tutorial</a>
*/
protected final <T extends CharSequence> T withMatch(T regex)
{
addMatcher(new PatternMatcher(regex.toString()));
return regex;
}
}