Home | History | Annotate | Download | only in mockito
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 package org.mockito;
      6 
      7 import org.mockito.internal.matchers.CapturingMatcher;
      8 import org.mockito.internal.matchers.VarargCapturingMatcher;
      9 import org.mockito.internal.progress.HandyReturnValues;
     10 
     11 import java.util.List;
     12 
     13 /**
     14  * Use it to capture argument values for further assertions.
     15  *
     16  * <p>
     17  * Mockito verifies argument values in natural java style: by using an equals() method.
     18  * This is also the recommended way of matching arguments because it makes tests clean & simple.
     19  * In some situations though, it is helpful to assert on certain arguments after the actual verification.
     20  * For example:
     21  * <pre class="code"><code class="java">
     22  *   ArgumentCaptor&lt;Person&gt; argument = ArgumentCaptor.forClass(Person.class);
     23  *   verify(mock).doSomething(argument.capture());
     24  *   assertEquals("John", argument.getValue().getName());
     25  * </code></pre>
     26  *
     27  * <p>
     28  * <strong>Warning:</strong> it is recommended to use ArgumentCaptor with verification <strong>but not</strong> with stubbing.
     29  * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.
     30  * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.
     31  *
     32  * <p>
     33  * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).
     34  * Both techniques can be used for making sure certain arguments where passed to mocks.
     35  * However, ArgumentCaptor may be a better fit if:
     36  * <ul>
     37  * <li>custom argument matcher is not likely to be reused</li>
     38  * <li>you just need it to assert on argument values to complete verification</li>
     39  * </ul>
     40  * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.
     41  *
     42  * <p>
     43  * This utility class <strong>*don't do any type checks*</strong>, the generic signatures are only there to avoid casting
     44  * in your code. If you want specific types, then you should do that the captured values.
     45  * This behavior might change (type checks could be added) in a
     46  * future major release.
     47  * <p>
     48  * There is an <strong>annotation</strong> that you might find useful: &#64;{@link Captor}
     49  * <p>
     50  * See the full documentation on Mockito in javadoc for {@link Mockito} class.
     51  *
     52  * @see Captor
     53  * @since 1.8.0
     54  */
     55 public class ArgumentCaptor<T> {
     56 
     57     HandyReturnValues handyReturnValues = new HandyReturnValues();
     58 
     59     private final CapturingMatcher<T> capturingMatcher = new CapturingMatcher<T>();
     60     private final VarargCapturingMatcher<T> varargCapturingMatcher = new VarargCapturingMatcher<T>();
     61     private final Class<T> clazz;
     62 
     63     /**
     64      * @deprecated
     65      *
     66      * <b>Please use factory method {@link ArgumentCaptor#forClass(Class)} to create captors</b>
     67      * <p>
     68      * This is required to avoid NullPointerExceptions when autoUnboxing primitive types.
     69      * See issue 99.
     70      * <p>
     71      * Example:
     72      * <pre class="code"><code class="java">
     73      *   ArgumentCaptor&lt;Person&gt; argument = ArgumentCaptor.forClass(Person.class);
     74      *   verify(mock).doSomething(argument.capture());
     75      *   assertEquals("John", argument.getValue().getName());
     76      * </code></pre>
     77      */
     78     @Deprecated
     79     public ArgumentCaptor() {
     80         this.clazz = null;
     81     }
     82 
     83     ArgumentCaptor(Class<T> clazz) {
     84         this.clazz = clazz;
     85     }
     86 
     87     /**
     88      * Use it to capture the argument. This method <b>must be used inside of verification</b>.
     89      * <p>
     90      * Internally, this method registers a special implementation of an {@link ArgumentMatcher}.
     91      * This argument matcher stores the argument value so that you can use it later to perform assertions.
     92      * <p>
     93      * See examples in javadoc for {@link ArgumentCaptor} class.
     94      *
     95      * @return null or default values
     96      */
     97     public T capture() {
     98         Mockito.argThat(capturingMatcher);
     99         return handyReturnValues.returnFor(clazz);
    100     }
    101 
    102     /**
    103      * Use it to capture the variable arguments. This method <b>must be used inside of verification</b>.
    104      * <p>
    105      * Internally, this method registers a special implementation of an {@link ArgumentMatcher}.
    106      * This argument matcher stores the variable arguments values so that you can use it later to perform assertions.
    107      * <p>
    108      * See examples in javadoc for {@link ArgumentCaptor} class.
    109      *
    110      * @return null or default values
    111      */
    112     public T captureVararg() {
    113         Mockito.argThat(varargCapturingMatcher);
    114         return handyReturnValues.returnFor(clazz);
    115     }
    116 
    117 
    118     /**
    119      * Returns the captured value of the argument.
    120      * <p>
    121      * If the method was called multiple times then it returns the latest captured value.
    122      * <p>
    123      * See examples in javadoc for {@link ArgumentCaptor} class.
    124      *
    125      * @return captured argument value
    126      */
    127     public T getValue() {
    128         return this.capturingMatcher.getLastValue();
    129     }
    130 
    131     /**
    132      * Returns the captured value of the variable arguments.
    133      * <p>
    134      * If the method was called multiple times then it returns the latest captured variable arguments.
    135      * <p>
    136      * See examples in javadoc for {@link ArgumentCaptor} class.
    137      *
    138      * @return captured varargs
    139      */
    140     public List<T> getVarargsValues() {
    141         return this.varargCapturingMatcher.getLastVarargs();
    142     }
    143 
    144     /**
    145      * Returns all captured values. Use it in case the verified method was called multiple times.
    146      * <p>
    147      * Example:
    148      * <pre class="code"><code class="java">
    149      *   ArgumentCaptor&lt;Person&gt; peopleCaptor = ArgumentCaptor.forClass(Person.class);
    150      *   verify(mock, times(2)).doSomething(peopleCaptor.capture());
    151      *
    152      *   List&lt;Person&gt; capturedPeople = peopleCaptor.getAllValues();
    153      *   assertEquals("John", capturedPeople.get(0).getName());
    154      *   assertEquals("Jane", capturedPeople.get(1).getName());
    155      * </code></pre>
    156      * See more examples in javadoc for {@link ArgumentCaptor} class.
    157      *
    158      * @return captured argument value
    159      */
    160     public List<T> getAllValues() {
    161         return this.capturingMatcher.getAllValues();
    162     }
    163 
    164     /**
    165      * Returns all captured variable arguments. Use it in case the verified method was called multiple times.
    166      * <p>
    167      * Example:
    168      * <pre class="code"><code class="java">
    169      *   ArgumentCaptor&lt;Person&gt; peopleFornamesCaptor = ArgumentCaptor.forClass(String.class);
    170      *   verify(mock, times(2)).doSomething(peopleFornamesCaptor.captureVarargs());
    171      *
    172      *   List&lt;String&gt; peopleFornames = peopleFornamesCaptor.getAllVarargs();
    173      *   assertThat(peopleFornames.get(0)).contains("John", "Carl");
    174      *   assertThat(peopleFornames.get(1)).contains("Janes", "Eloise", "Lois");
    175      * </code></pre>
    176      * See more examples in javadoc for {@link ArgumentCaptor} class.
    177      *
    178      * @return all captured varargs
    179      */
    180     public List<List<T>> getAllVarargsValues() {
    181         return this.varargCapturingMatcher.getAllVarargs();
    182     }
    183 
    184     /**
    185      * Build a new <code>ArgumentCaptor</code>.
    186      * <p>
    187      * Note that an <code>ArgumentCaptor</code> <b>*don't do any type checks*</b>, it is only there to avoid casting
    188      * in your code. This might however change (type checks could be added) in a
    189      * future major release.
    190      *
    191      * @param clazz Type matching the parameter to be captured.
    192      * @param <T> Type of clazz
    193      * @return A new ArgumentCaptor
    194      */
    195     public static <T> ArgumentCaptor<T> forClass(Class<T> clazz) {
    196         return new ArgumentCaptor<T>(clazz);
    197     }
    198 }