All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mockit.Expectations Maven / Gradle / Ivy

Go to download

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;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;

import mockit.internal.expectations.RecordAndReplayExecution;
import mockit.internal.expectations.RecordPhase;

/**
 * Used to record expectations on {@linkplain Mocked mocked} types and their instances.
 * 

* Each recorded expectation is intended to match one or more method or constructor invocations, that we expect will * occur during the execution of code under test, and which need to exhibit some specific behavior for the purposes of * the test. When a match is detected, the recorded {@linkplain #result result} (if any) is returned to the caller. * Alternatively, a recorded exception/error is thrown, or an arbitrary {@linkplain Delegate delegate} method is * executed. *

* Expectations are recorded simply by invoking the desired method or constructor on the mocked type/instance, during * the initialization of an Expectations object. This is done by instantiating an anonymous subclass * containing an instance initialization body, or as we call it, an expectation block: * *

{@code
 * // Record one or more expectations on available mocked types/instances.
 * new Expectations() {{
 *    mock1.expectedMethod(anyInt); result = 123; times = 2;
 *    mock2.anotherExpectedMethod(1, "test"); result = "Abc";
 * }};
 *
 * // Exercise tested code, with previously recorded expectations now available for replay.
 * codeUnderTest.doSomething();
 * }
* * During replay, invocations matching a recorded expectation must occur at least once (unless specified * otherwise); if, by the end of the test, no matching invocation occurred for a given recorded expectation, the test * will fail with a MissingInvocation error. *

* When multiple expectations are recorded, matching invocations are allowed to occur in a different order. So, * the order in which expectations are recorded is not significant. *

* Besides the special {@link #result} field already mentioned, there are several other fields and methods which can be * used inside the expectation block: a) {@link #returns(Object, Object, Object...)}, a convenience method for returning * a sequence of values; b) argument matchers such as {@link #anyInt}, {@link #anyString}, * {@link #withNotNull()}, etc., which relax or constrain the matching of argument values; c) the {@link #times}, * {@link #minTimes}, and {@link #maxTimes} fields, which relax or constrain the expected and/or allowed number of * matching invocations. *

* By default, the exact instance on which instance method invocations will occur during replay is not verified * to be the same as the instance used when recording the expectation. That said, instance-specific matching can be * obtained by declaring the mocked type as {@linkplain Injectable @Injectable}, or by declaring multiple mock fields * and/or mock parameters of the same mocked type (so that separate expectations can be recorded for each mock * instance). *

* Invocations occurring during replay, whether they matched recorded expectations or not, can be explicitly verified * after exercising the code under test. To that end, we use a set of complementary base classes: * {@link Verifications}, {@link VerificationsInOrder}, and {@link FullVerifications}. Similar to expectation blocks, * these classes allow us to create verification blocks. * * @see #Expectations() * @see #Expectations(Object...) * @see Tutorial */ public class Expectations extends Invocations { /** * A value assigned to this field will be taken as the result for the expectation that is being recorded. *

* If the value is a {@link Throwable} then it will be thrown when a matching invocation later occurs. * Otherwise, it's assumed to be a return value for a non-void method, and will be returned * from a matching invocation. *

* If no result is recorded for a given expectation, then all matching invocations will return the appropriate * default value according to the method return type: *

    *
  • Most java.lang types (String, Object, etc.): returns * null.
  • *
  • java.math types (BigDecimal, etc.): returns null.
  • *
  • Primitive/wrapper types: returns the standard default value (false for * boolean/Boolean, 0 for int/Integer, and so on).
  • *
  • java.util.List, java.util.Collection, or java.lang.Iterable: returns * {@link Collections#EMPTY_LIST}.
  • *
  • java.util.Iterator or java.util.ListIterator: returns an empty iterator.
  • *
  • java.util.Set: returns {@link Collections#EMPTY_SET}.
  • *
  • java.util.SortedSet: returns an unmodifiable empty sorted set.
  • *
  • java.util.Map: returns {@link Collections#EMPTY_MAP}.
  • *
  • java.util.SortedMap: returns an unmodifiable empty sorted map.
  • *
  • java.util.Optional: returns {@link Optional#empty()}.
  • *
  • Other reference types: returns a mocked instance through cascading.
  • *
  • Array types: returns an array with zero elements (empty) in each dimension.
  • *
* When an expectation is recorded for a method which actually returns an exception or error (as opposed to * throwing one), then the {@link #returns(Object, Object, Object...)} method should be used instead, as it * only applies to return values. *

* Assigning a value whose type differs from the method return type will cause an * IllegalArgumentException to be thrown, unless it can be safely converted to the return type. One * such conversion is from an array to a collection or iterator. Another is from an array of at least two dimensions * to a map, with the first dimension providing the keys and the second the values. Yet another conversion is from a * single value to a container type holding that value. *

* A sequence of consecutive results can be recorded simply by assigning the field multiple times for the * same expectation. Alternatively, the desired sequence of results for a single-valued return type can be recorded * by assigning an array, an {@link Iterable}, or an {@link Iterator} containing the individual results in order. *

* Results that depend on some programming logic can be provided through a {@linkplain Delegate} object assigned to * the field. This applies to void and non-void methods, as well as to constructors. * * @see Tutorial */ @Nullable protected Object result; /** * Registers one or more expectations recorded on available mocked types and/or mocked instances, as written inside * the instance initialization body of an anonymous subclass. * * @see #Expectations(Object...) * @see Tutorial */ protected Expectations() { RecordAndReplayExecution execution = new RecordAndReplayExecution(this, (Object[]) null); // noinspection ConstantConditions currentPhase = execution.getRecordPhase(); } /** * Same as {@link #Expectations()}, except that one or more objects will be partially mocked according to the * expectations recorded in the expectation block. *

* During replay, any invocations to instance methods on these objects will execute real production code, unless a * matching expectation was recorded. * * @param objectsToBePartiallyMocked * one or more objects to be partially mocked * * @throws IllegalArgumentException * if given a Class object, or if given a value/instance of an interface, an annotation, an * array, a primitive/wrapper type, a synthetic class, or a * {@linkplain java.lang.reflect.Proxy#isProxyClass(Class) proxy class} * * @see Tutorial */ protected Expectations(@NonNull Object... objectsToBePartiallyMocked) { RecordAndReplayExecution execution = new RecordAndReplayExecution(this, objectsToBePartiallyMocked); // noinspection ConstantConditions currentPhase = execution.getRecordPhase(); } /** * Specifies that the previously recorded method invocation will return a given sequence of values during replay. *

* Calling this method is equivalent to assigning the {@link #result} field two or more times in sequence, or * assigning it a single time with an array or iterable containing the same sequence of values. *

* Certain data conversions will be applied, depending on the return type of the recorded method: *

    *
  1. If the return type is iterable and can receive a {@link List} value, then the given sequence of values will * be converted into an ArrayList; this list will then be returned by matching invocations at replay * time.
  2. *
  3. If the return type is SortedSet or a sub-type, then the given sequence of values will be * converted into a TreeSet; otherwise, if it is Set or a sub-type, then a * LinkedHashSet will be created to hold the values; the set will then be returned by matching * invocations at replay time.
  4. *
  5. If the return type is Iterator or a sub-type, then the given sequence of values will be * converted into a List and the iterator created from this list will be returned by matching * invocations at replay time.
  6. *
  7. If the return type is an array, then the given sequence of values will be converted to an array of the same * type, which will be returned by matching invocations at replay time.
  8. *
* The current expectation will have its upper invocation count automatically set to the total number of values * specified to be returned. This upper limit can be overridden through the maxTimes field, if * necessary. * * @param firstValue * the first value to be returned at replay time * @param secondValue * the second value to be returned at replay time * @param remainingValues * any remaining values to be returned, in the same order * * @see Tutorial */ protected final void returns(@Nullable Object firstValue, @Nullable Object secondValue, @NonNull Object... remainingValues) { int n = remainingValues.length; Object[] values = new Object[2 + n]; values[0] = firstValue; values[1] = secondValue; System.arraycopy(remainingValues, 0, values, 2, n); ((RecordPhase) currentPhase).addSequenceOfReturnValues(values); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy