- Inconsistent argument matcher usage
- Explicit initialization of @Captor field is not required
- @Captor field must be of the type ArgumentCaptor
- Generic inferred ArgumentCaptor creation
Argument matchers are used inconsistently (and incorrectly) when, during stubbing, matcher and non-matcher arguments are used in a mixed manner. That is not permitted by Mockito, and test execution fails when it encounters this problem. As per Mockito documentation:
If you are using argument matchers, all arguments have to be provided by matchers.
For example, the followings are invalid, and would block test execution.
Mockito.when(mock.method(eq("some string"), 25)).thenReturn(10);
//or
Mockito.when(mock.method("some string", geq(25))).thenReturn(10);
The following ways of stubbing are supported by this inspection:
Mockito.when()
,BDDMockito.given()
,Mockito.do...().when()
, matchers inAdditionalMatchers
You can find more information in the official documents and source code:
- Argument matchers documentation
- ArgumentMatchers javadoc
- org.mockito.internal.exceptions.Reporter#invalidUseOfMatchers(int, List)
- org.mockito.internal.exceptions.Reporter#incorrectUseOfAdditionalMatchers(String, int, Collection)
SonarLint also have a rule for this validation: Mockito argument matchers should be used on all parameters
Since @Captor
annotated fields are initialized automagically by Mockito via MockitoJUnitRunner
, MockitoJUnit.rule()
or
MockitoAnnotations.initMocks()/openMocks()
, there is no need to explicitly initialize them.
This inspection reports ArgumentCaptor
type @Captor
fields that have an initializer specified.
public class CaptorTest {
@Captor
public ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
}
You can also apply a quick fix (Remove initializer) on it, so that the initializer may be removed. The code will then become:
public class CaptorTest {
@Captor
public ArgumentCaptor<String> captor;
}
Fields that are annotated as @Captor
must have ArgumentCaptor
as their type, otherwise Mockito will fail with a message saying the type must be ArgumentCaptor. You can find the corresponding logic in
org.mockito.internal.configuration.CaptorAnnotationProcessor.
This inspection reports fields that are annotated as @Captor
but their types are not ArgumentCaptor
.
It also provides a quick fix (Convert field type to ArgumentCaptor<>) to convert the field type to ArgumentCaptor with the appropriate generic type.
//-- arrays --
@Captor
String[] captor; //before
@Captor
ArgumentCaptor<String[]> captor; //after
//-- primitive types --
@Captor
char captor; //before
@Captor
ArgumentCaptor<Character> captor; //after: field type is replaced with its boxed type
//-- types with generic types --
@Captor
List<List<String>> captor; //before
@Captor
ArgumentCaptor<List<List<String>>> captor; //after
Mockito 5.7.0 introduced the ArgumentCaptor.captor()
method
for captor creation, so that the captor type is not determined by the class passed in at creation, instead by the type of the variable/field it is assigned to.
This method throws an exception if objects are passed in, thus this inspection reports calls to this method when it finds at least one such argument.