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 static org.mockito.internal.util.Primitives.defaultValue;
      8 
      9 import java.util.List;
     10 
     11 import org.mockito.internal.matchers.CapturingMatcher;
     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  * Example of capturing varargs:
     28  * <pre class="code"><code class="java">
     29  *   //capturing varargs:
     30  *   ArgumentCaptor&lt;Person&gt; varArgs = ArgumentCaptor.forClass(Person.class);
     31  *   verify(mock).varArgMethod(varArgs.capture());
     32  *   List expected = asList(new Person("John"), new Person("Jane"));
     33  *   assertEquals(expected, varArgs.getAllValues());
     34  * </code></pre>
     35  *
     36  * <p>
     37  * <strong>Warning:</strong> it is recommended to use ArgumentCaptor with verification <strong>but not</strong> with stubbing.
     38  * Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.
     39  * Also it may reduce defect localization because if stubbed method was not called then no argument is captured.
     40  *
     41  * <p>
     42  * In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).
     43  * Both techniques can be used for making sure certain arguments where passed to mocks.
     44  * However, ArgumentCaptor may be a better fit if:
     45  * <ul>
     46  * <li>custom argument matcher is not likely to be reused</li>
     47  * <li>you just need it to assert on argument values to complete verification</li>
     48  * </ul>
     49  * Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.
     50  *
     51  * <p>
     52  * This utility class <strong>*don't do any type checks*</strong>, the generic signatures are only there to avoid casting
     53  * in your code.
     54  * <p>
     55  * There is an <strong>annotation</strong> that you might find useful: &#64;{@link Captor}
     56  * <p>
     57  * See the full documentation on Mockito in javadoc for {@link Mockito} class.
     58  *
     59  * @see Captor
     60  * @since 1.8.0
     61  */
     62 public class ArgumentCaptor<T> {
     63 
     64 
     65     private final CapturingMatcher<T> capturingMatcher = new CapturingMatcher<T>();
     66     private final Class<? extends T> clazz;
     67 
     68     private ArgumentCaptor(Class<? extends T> clazz) {
     69         this.clazz = clazz;
     70     }
     71 
     72     /**
     73      * Use it to capture the argument. This method <b>must be used inside of verification</b>.
     74      * <p>
     75      * Internally, this method registers a special implementation of an {@link ArgumentMatcher}.
     76      * This argument matcher stores the argument value so that you can use it later to perform assertions.
     77      * <p>
     78      * See examples in javadoc for {@link ArgumentCaptor} class.
     79      *
     80      * @return null or default values
     81      */
     82     public T capture() {
     83         Mockito.argThat(capturingMatcher);
     84         return defaultValue(clazz);
     85     }
     86 
     87     /**
     88      * Returns the captured value of the argument. When capturing varargs use {@link #getAllValues()}.
     89      * <p>
     90      * If verified method was called multiple times then this method it returns the latest captured value.
     91      * <p>
     92      * See examples in javadoc for {@link ArgumentCaptor} class.
     93      *
     94      * @return captured argument value
     95      */
     96     public T getValue() {
     97         return this.capturingMatcher.getLastValue();
     98     }
     99 
    100     /**
    101      * Returns all captured values. Use it when capturing varargs or when the verified method was called multiple times.
    102      * When varargs method was called multiple times, this method returns merged list of all values from all invocations.
    103      * <p>
    104      * Example:
    105      * <pre class="code"><code class="java">
    106      *   mock.doSomething(new Person("John");
    107      *   mock.doSomething(new Person("Jane");
    108      *
    109      *   ArgumentCaptor&lt;Person&gt; peopleCaptor = ArgumentCaptor.forClass(Person.class);
    110      *   verify(mock, times(2)).doSomething(peopleCaptor.capture());
    111      *
    112      *   List&lt;Person&gt; capturedPeople = peopleCaptor.getAllValues();
    113      *   assertEquals("John", capturedPeople.get(0).getName());
    114      *   assertEquals("Jane", capturedPeople.get(1).getName());
    115      * </pre>
    116      *
    117      * Example of capturing varargs:
    118      * <pre class="code"><code class="java">
    119      *   mock.countPeople(new Person("John"), new Person("Jane"); //vararg method
    120      *
    121      *   ArgumentCaptor&lt;Person&gt; peopleCaptor = ArgumentCaptor.forClass(Person.class);
    122      *
    123      *   verify(mock).countPeople(peopleCaptor.capture());
    124      *
    125      *   List expected = asList(new Person("John"), new Person("Jane"));
    126      *   assertEquals(expected, peopleCaptor.getAllValues());
    127      * </code></pre>
    128      * See more examples in javadoc for {@link ArgumentCaptor} class.
    129      *
    130      * @return captured argument value
    131      */
    132     public List<T> getAllValues() {
    133         return this.capturingMatcher.getAllValues();
    134     }
    135 
    136     /**
    137      * Build a new <code>ArgumentCaptor</code>.
    138      * <p>
    139      * Note that an <code>ArgumentCaptor</code> <b>*don't do any type checks*</b>, it is only there to avoid casting
    140      * in your code. This might however change (type checks could be added) in a
    141      * future major release.
    142      *
    143      * @param clazz Type matching the parameter to be captured.
    144      * @param <S> Type of clazz
    145      * @param <U> Type of object captured by the newly built ArgumentCaptor
    146      * @return A new ArgumentCaptor
    147      */
    148     public static <U,S extends U> ArgumentCaptor<U> forClass(Class<S> clazz) {
    149         return new ArgumentCaptor<U>(clazz);
    150     }
    151 }
    152