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 }