View Javadoc
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.lang.reflect.Member;
12  
13  import mockit.internal.BaseInvocation;
14  
15  import org.checkerframework.checker.index.qual.NonNegative;
16  
17  /**
18   * A context object representing the current invocation to a mocked or faked method/constructor, to be passed as the
19   * <em>first</em> parameter of the corresponding delegate/fake method implementation.
20   * <p>
21   * With the <em>Mocking</em> API, this parameter can appear in delegate methods implemented in {@link Delegate} classes.
22   * With the <em>Faking</em> API, it can appear in {@link Mock @Mock} methods.
23   *
24   * @see #getInvokedInstance()
25   * @see #getInvokedArguments()
26   * @see #getInvocationCount()
27   * @see #getInvocationIndex()
28   * @see #proceed(Object...)
29   * @see <a href="http://jmockit.github.io/tutorial/Mocking.html#delegates" target="tutorial">Tutorial (mocking)</a>
30   * @see <a href="http://jmockit.github.io/tutorial/Faking.html#invocation" target="tutorial">Tutorial (faking)</a>
31   */
32  public class Invocation {
33  
34      /** The invoked instance. */
35      @Nullable
36      private final Object invokedInstance;
37  
38      /** The invoked arguments. */
39      @NonNull
40      private final Object[] invokedArguments;
41  
42      /** The invocation count. */
43      @NonNegative
44      private final int invocationCount;
45  
46      /**
47       * For internal use only.
48       *
49       * @param invokedInstance
50       *            the invoked instance
51       * @param invokedArguments
52       *            the invoked arguments
53       * @param invocationCount
54       *            the invocation count
55       */
56      protected Invocation(@Nullable Object invokedInstance, @NonNull Object[] invokedArguments,
57              @NonNegative int invocationCount) {
58          this.invokedInstance = invokedInstance;
59          this.invokedArguments = invokedArguments;
60          this.invocationCount = invocationCount;
61      }
62  
63      /**
64       * Returns the instance on which the current invocation was made, or <code>null</code> for a <code>static</code>
65       * method invocation.
66       *
67       * @param <T>
68       *            the generic type
69       *
70       * @return the invoked instance
71       */
72      @Nullable
73      public final <T> T getInvokedInstance() {
74          // noinspection unchecked
75          return (T) invokedInstance;
76      }
77  
78      /**
79       * Returns the <code>Method</code> or <code>Constructor</code> object corresponding to the target method or
80       * constructor, respectively.
81       *
82       * @param <M>
83       *            the generic type
84       *
85       * @return the invoked member
86       */
87      @NonNull
88      public final <M extends Member> M getInvokedMember() {
89          // noinspection unchecked,ClassReferencesSubclass
90          return (M) ((BaseInvocation) this).getRealMember();
91      }
92  
93      /**
94       * Returns the actual argument values passed in the invocation to the target method/constructor.
95       *
96       * @return the invoked arguments
97       */
98      @NonNull
99      public final Object[] getInvokedArguments() {
100         return invokedArguments;
101     }
102 
103     /**
104      * Returns the current invocation count. The first invocation starts at 1 (one).
105      *
106      * @return the invocation count
107      */
108     @NonNegative
109     public final int getInvocationCount() {
110         return invocationCount;
111     }
112 
113     /**
114      * Returns the index for the current invocation. The first invocation starts at 0 (zero). Note that this is
115      * equivalent to {@link #getInvocationCount()} - 1.
116      *
117      * @return the invocation index
118      */
119     public final int getInvocationIndex() {
120         return invocationCount - 1;
121     }
122 
123     /**
124      * Allows execution to proceed into the real implementation of the target method/constructor.
125      * <p>
126      * In the case of a method, the real implementation is executed with the argument values originally received or
127      * explicitly given as replacement. Whatever comes out (either a return value or a thrown exception/error) becomes
128      * the result for this execution of the method.
129      * <p>
130      * In the case of a constructor, the real constructor implementation code which comes after the necessary call to
131      * "<code>super</code>" is executed, using the original argument values; replacement arguments are not supported. If
132      * the execution of said code throws an exception or error, it is propagated out to the caller of the target
133      * constructor. Contrary to proceeding into a method, it's not possible to actually execute test code inside the
134      * delegate or fake method after proceeding into the real constructor, nor to proceed into it more than once.
135      *
136      * @param <T>
137      *            the return type of the target method
138      * @param replacementArguments
139      *            the argument values to be passed to the real method, as replacement for the values received by the
140      *            delegate or fake method; if those received values should be passed without replacement, then this
141      *            method should be called with no values
142      *
143      * @return the same value returned by the target method, if any
144      *
145      * @throws UnsupportedOperationException
146      *             if attempting to proceed into a target method which does not belong to an {@linkplain Injectable
147      *             injectable mocked type} nor to a {@linkplain Expectations#Expectations(Object...) partially mocked
148      *             object}, into a <code>native</code> method, or into an interface or abstract method
149      *
150      * @see <a href="http://jmockit.github.io/tutorial/Faking.html#proceed" target="tutorial">Tutorial</a>
151      */
152     @Nullable
153     public final <T> T proceed(@Nullable Object... replacementArguments) {
154         // noinspection ClassReferencesSubclass
155         return ((BaseInvocation) this).doProceed(replacementArguments);
156     }
157 }