1 /*
2 * MIT License
3 * Copyright (c) 2006-2025 JMockit developers
4 * See LICENSE file for full license text.
5 */
6 package mockit;
7
8 import edu.umd.cs.findbugs.annotations.NonNull;
9 import edu.umd.cs.findbugs.annotations.Nullable;
10
11 import java.util.List;
12
13 import mockit.internal.expectations.BaseVerificationPhase;
14 import mockit.internal.expectations.RecordAndReplayExecution;
15 import mockit.internal.expectations.argumentMatching.AlwaysTrueMatcher;
16 import mockit.internal.state.TestRun;
17
18 /**
19 * Used to <em>verify</em> a set of expectations on available {@linkplain Mocked mocked} types and/or instances, against
20 * the invocations which actually occurred during the test. As such, these verifications can only appear <em>after</em>
21 * having exercised the code under test.
22 * <p>
23 * An expectation verification attempts to match a number of method or constructor invocations, that we expect have
24 * occurred during the execution of code under test. By default, <em>at least one</em> matching invocation must be found
25 * for the verification to be successful; if no matching invocations are found, an assertion error is thrown.
26 * <p>
27 * Expectations are verified simply by invoking the desired method or constructor on a mocked type/instance, during the
28 * initialization of a <code>Verifications</code> object. This is done by instantiating an anonymous subclass containing
29 * an instance initialization body, or as we call it, a <em>verification block</em>:
30 *
31 * <pre>{@code
32 * // Exercise tested code.
33 * codeUnderTest.doSomething();
34 *
35 * // Now verify that the expected invocations actually occurred (in any order).
36 * new Verifications() {{
37 * <strong>mock1</strong>.expectedMethod(anyInt);
38 * <strong>mock2</strong>.anotherExpectedMethod(1, "test"); times = 2;
39 * }};
40 * }</pre>
41 *
42 * The relative order between the invocations that match two or more verifications is not taken into consideration; when
43 * that is desired, the {@link VerificationsInOrder} class should be used instead.
44 * <p>
45 * Not all invocations that occurred during the execution of code under test need to be explicitly verified in a
46 * verification block. If that is desired, we can make sure that <em>all</em> such invocations are verified, by using
47 * the {@link FullVerifications} class.
48 *
49 * @see #Verifications()
50 * @see #withCapture()
51 * @see Expectations
52 * @see <a href="http://jmockit.github.io/tutorial/Mocking.html#verification" target="tutorial">Tutorial</a>
53 */
54 public class Verifications extends Invocations {
55 /**
56 * Begins a set of unordered expectation verifications, on the available mocked types and/or mocked instances. Such
57 * verifications are meant to be executed <em>after</em> the call to code under test has been made.
58 */
59 protected Verifications() {
60 this(false, (Object[]) null);
61 }
62
63 /**
64 * Instantiates a new verifications.
65 *
66 * @param inOrder
67 * the in order
68 * @param mockedTypesAndInstancesToVerify
69 * the mocked types and instances to verify
70 */
71 Verifications(boolean inOrder, @Nullable Object... mockedTypesAndInstancesToVerify) {
72 RecordAndReplayExecution instance = TestRun.getRecordAndReplayForVerifications();
73 currentPhase = instance.startVerifications(inOrder, mockedTypesAndInstancesToVerify);
74 }
75
76 /**
77 * Captures the argument value passed into the associated expectation parameter, for a matching invocation that
78 * occurred when the tested code was exercised. This method should be used in a local variable assignment expression
79 * inside a verification block. For example:
80 *
81 * <pre>{@code
82 * codeUnderTest.doSomething();
83 *
84 * new Verifications() {{
85 * String <strong>name</strong>;
86 * int <strong>age</strong>;
87 * personDAOMock.create(<strong>age</strong> = <em>withCapture()</em>, <strong>name</strong> = <em>withCapture()</em>);
88 * assertFalse(<strong>name</strong>.isEmpty());
89 * assertTrue(<strong>age</strong> >= 18);
90 * }};
91 * }</pre>
92 *
93 * If there is more than one matching invocation, then only the last one to have occurred is considered. Apart from
94 * capturing received argument values, this method has the same effect as the {@link #any} argument matcher.
95 * <p>
96 * When an argument matcher is used for a regular (ie, non-varargs) parameter in a call to a mocked
97 * method/constructor, it's <em>not</em> necessary to also use matchers for the other parameters. So, it's valid to
98 * mix the use of matchers with given values. Arguments given as literals, local variables, or fields, will be
99 * implicitly matched as if {@link #withEqual(Object)} had been used. In the special case of a varargs method,
100 * however, this flexibility is not available: if a matcher is used for any regular parameter, or for any element in
101 * the varargs array, then a matcher <em>must</em> be used for every other parameter and varargs element.
102 *
103 * @param <T>
104 * the generic type
105 *
106 * @return the captured argument value
107 *
108 * @see #withCapture(List)
109 * @see #withCapture(Object)
110 * @see <a href="http://jmockit.github.io/tutorial/Mocking.html#withCapture" target="tutorial">Tutorial</a>
111 */
112 @Nullable
113 protected final <T> T withCapture() {
114 currentPhase.addArgMatcher(AlwaysTrueMatcher.ANY_VALUE);
115 return null;
116 }
117
118 /**
119 * Captures new instances of type <code>T</code> that were created by the code under test. Said instances are only
120 * those which were created through constructor invocations matching the constructor verification that was passed as
121 * argument in a call to this method. For example:
122 *
123 * <pre>{@code
124 * codeUnderTest.doSomething();
125 *
126 * new Verifications() {{
127 * <strong>List<Person> newPersons = withCapture(new Person());</strong>
128 * Person newPerson = newPersons.get(0);
129 *
130 * Person personCreated;
131 * personDAOMock.create(personCreated = withCapture());
132 *
133 * assertSame(newPerson, personCreated);
134 * }};
135 * }</pre>
136 *
137 * Note this is not meant be used as an argument matcher.
138 *
139 * @param <T>
140 * the generic type
141 * @param constructorVerification
142 * a new instance of the desired mocked class, created through a regular constructor verification
143 *
144 * @return a list with the (zero, one, or more) captured new instances that match the verified constructor
145 * invocation
146 *
147 * @see #withCapture()
148 * @see #withCapture(List)
149 * @see <a href="http://jmockit.github.io/tutorial/Mocking.html#withCapture" target="tutorial">Tutorial</a>
150 */
151 @NonNull
152 protected final <T> List<T> withCapture(@NonNull T constructorVerification) {
153 return ((BaseVerificationPhase) currentPhase).getNewInstancesMatchingVerifiedConstructorInvocation();
154 }
155 }