/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import java.util.*; import javax.annotation.*; import mockit.internal.expectations.*; import mockit.internal.expectations.argumentMatching.*; import mockit.internal.state.*; /** * Used to <em>verify</em> a set of expectations on available {@linkplain Mocked mocked} types and/or instances, * against the invocations which actually occurred during the test. * As such, these verifications can only appear <em>after</em> having exercised the code under test. * <p/> * An expectation verification attempts to match a number of method or constructor invocations, that we expect have * occurred during the execution of code under test. * By default, <em>at least one</em> matching invocation must be found for the verification to be successful; if no * matching invocations are found, an assertion error is thrown. * <p/> * Expectations are verified simply by invoking the desired method or constructor on a mocked type/instance, during * the initialization of a {@code Verifications} object. * Typically, this is done by instantiating an anonymous subclass containing an instance initialization body, or as we * call it, a <em>verification block</em>: * <pre> * // Exercise tested code. * codeUnderTest.doSomething(); * * // Now verify that the expected invocations actually occurred (in any order). * new Verifications() {{ * <strong>mock1</strong>.expectedMethod(anyInt); * <strong>mock2</strong>.anotherExpectedMethod(1, "test"); times = 2; * }}; * </pre> * The relative order between the invocations that match two or more verifications is not taken into consideration; when * that is desired, the {@link VerificationsInOrder} class should be used instead. * <p/> * Naturally, not all invocations that occurred during the execution of code under test need to be explicitly verified * in a verification block. * If desired, however, we can make sure that <em>all</em> such invocations are verified, by using the * {@link FullVerifications} class instead. * * @see #Verifications() * @see #withCapture() * @see Expectations * @see <a href="http://jmockit.org/tutorial/Mocking.html#verification">Tutorial</a> */ public abstract class Verifications extends Invocations { @Nonnull final BaseVerificationPhase verificationPhase; /** * Begins a set of unordered expectation verifications, on the available mocked types and/or mocked instances. * Such verifications are meant to be executed <em>after</em> the call to code under test has been made. */ protected Verifications() { this(false); } Verifications(boolean inOrder) { RecordAndReplayExecution instance = TestRun.getRecordAndReplayForVerifications(); verificationPhase = instance.startVerifications(inOrder); } @Nonnull @Override final BaseVerificationPhase getCurrentPhase() { return verificationPhase; } /** * Captures the argument value passed into the associated expectation parameter, for a matching invocation that * occurred when the tested code was exercised. * This method should be used in a local variable assignment expression inside a verification block. * For example: * <pre> * codeUnderTest.doSomething(); * * new Verifications() {{ * String <strong>name</strong>; * int <strong>age</strong>; * personDAOMock.create(<strong>age</strong> = <em>withCapture()</em>, <strong>name</strong> = <em>withCapture()</em>); * assertFalse(<strong>name</strong>.isEmpty()); * assertTrue(<strong>age</strong> >= 18); * }}; * </pre> * If there is more than one matching invocation, then only the last one to have occurred is considered. * 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. * * @return the captured argument value * * @see #withCapture(List) * @see #withCapture(Object) * @see <a href="http://jmockit.org/tutorial/Mocking.html#withCapture">Tutorial</a> */ protected final <T> T withCapture() { verificationPhase.addArgMatcher(AlwaysTrueMatcher.ANY_VALUE); //noinspection ConstantConditions return null; } /** * Captures new instances of type {@code T} that were created by the code under test. * Said instances are only those which were created through constructor invocations matching the constructor * verification that was passed as argument in a call to this method. * For example: * <pre> * codeUnderTest.doSomething(); * * new Verifications() {{ * <strong>List<Person> newPersons = withCapture(new Person());</strong> * Person newPerson = newPersons.get(0); * * Person personCreated; * personDAOMock.create(personCreated = withCapture()); * * assertSame(newPerson, personCreated); * }}; * </pre> * Note this is not meant be used as an argument matcher. * * @param constructorVerification a new instance of the desired mocked class, created through a regular constructor * verification * * @return a list with the (zero, one, or more) captured new instances that match the verified constructor invocation * * @see #withCapture() * @see #withCapture(List) * @see <a href="http://jmockit.org/tutorial/Mocking.html#withCapture">Tutorial</a> */ protected final <T> List<T> withCapture(@SuppressWarnings("unused") T constructorVerification) { return verificationPhase.getNewInstancesMatchingVerifiedConstructorInvocation(); } }