org.mockito.ArgumentCaptor Maven / Gradle / Ivy
Show all versions of mockito-all Show documentation
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito;
import org.mockito.internal.matchers.CapturingMatcher;
import org.mockito.internal.progress.HandyReturnValues;
import java.util.List;
/**
* Use it to capture argument values for further assertions.
*
*
* Mockito verifies argument values in natural java style: by using an equals() method.
* This is also the recommended way of matching arguments because it makes tests clean & simple.
* In some situations though, it is helpful to assert on certain arguments after the actual verification.
* For example:
*
* ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
* verify(mock).doSomething(argument.capture());
* assertEquals("John", argument.getValue().getName());
*
*
*
* Warning: it is recommended to use ArgumentCaptor with verification but not with stubbing.
* Using ArgumentCaptor with stubbing may decrease test readability because captor is created outside of assert (aka verify or 'then') block.
* Also it may reduce defect localization because if stubbed method was not called then no argument is captured.
*
*
* In a way ArgumentCaptor is related to custom argument matchers (see javadoc for {@link ArgumentMatcher} class).
* Both techniques can be used for making sure certain arguments where passed to mocks.
* However, ArgumentCaptor may be a better fit if:
*
* - custom argument matcher is not likely to be reused
* - you just need it to assert on argument values to complete verification
*
* Custom argument matchers via {@link ArgumentMatcher} are usually better for stubbing.
*
*
* This utility class *don't do any type checks*, the generic signatures are only there to avoid casting
* in your code. If you want specific types, then you should do that the captured values.
* This behavior might change (type checks could be added) in a
* future major release.
*
* There is an annotation that you might find useful: @{@link Captor}
*
* See the full documentation on Mockito in javadoc for {@link Mockito} class.
*
* @see Captor
* @since 1.8.0
*/
public class ArgumentCaptor {
HandyReturnValues handyReturnValues = new HandyReturnValues();
private final CapturingMatcher capturingMatcher = new CapturingMatcher();
private final Class clazz;
/**
* @deprecated
*
* Please use factory method {@link ArgumentCaptor#forClass(Class)} to create captors
*
* This is required to avoid NullPointerExceptions when autoUnboxing primitive types.
* See issue 99.
*
* Example:
*
* ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
* verify(mock).doSomething(argument.capture());
* assertEquals("John", argument.getValue().getName());
*
*/
@Deprecated
public ArgumentCaptor() {
this.clazz = null;
}
ArgumentCaptor(Class clazz) {
this.clazz = clazz;
}
/**
* Use it to capture the argument. This method must be used inside of verification.
*
* Internally, this method registers a special implementation of an {@link ArgumentMatcher}.
* This argument matcher stores the argument value so that you can use it later to perform assertions.
*
* See examples in javadoc for {@link ArgumentCaptor} class.
*
* @return null
*/
public T capture() {
Mockito.argThat(capturingMatcher);
return handyReturnValues.returnFor(clazz);
}
/**
* Returns the captured value of the argument.
*
* If the method was called multiple times then it returns the latest captured value
*
* See examples in javadoc for {@link ArgumentCaptor} class.
*
* @return captured argument value
*/
public T getValue() {
return this.capturingMatcher.getLastValue();
}
/**
* Returns all captured values. Use it in case the verified method was called multiple times.
*
* Example:
*
* ArgumentCaptor<Person> peopleCaptor = ArgumentCaptor.forClass(Person.class);
* verify(mock, times(2)).doSomething(peopleCaptor.capture());
*
* List<Person> capturedPeople = peopleCaptor.getAllValues();
* assertEquals("John", capturedPeople.get(0).getName());
* assertEquals("Jane", capturedPeople.get(1).getName());
*
* See more examples in javadoc for {@link ArgumentCaptor} class.
*
* @return captured argument value
*/
public List getAllValues() {
return this.capturingMatcher.getAllValues();
}
/**
* Build a new ArgumentCaptor
.
*
* Note that an ArgumentCaptor
*don't do any type checks*, it is only there to avoid casting
* in your code. This might however change (type checks could be added) in a
* future major release.
*
* @param clazz Type matching the parameter to be captured.
* @param Type of clazz
* @return A new ArgumentCaptor
*/
public static ArgumentCaptor forClass(Class clazz) {
return new ArgumentCaptor(clazz);
}
}