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