Issue
I am writing a ParametrizedTest in Junit. The argument for that test is from an enum source.
I want to construct an object with that enum and make the mocked method return that object.
However, when I try to do that, I am getting (what I think is) an irrelevant error message.
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here:
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
Here is the code:
public static enum CodeEnum {
S1("S1"),
S2("S2)
}
@RunWith(MockitoJUnitRunner.class)
public class FooTest {
@Mocked
MockedObject mockedObject;
@InjectMocks
Foo underTest
@ParameterizedTest
@EnumSource(CodeEnum.class)
public void test_ParametrizedTest(CodeEnum enum) {
Output expectedReturn = Output.builder().code(enum).build();
// Given
when(mockedObject.method(any()))
.thenReturn(expectedReturn);
// when
val result = underTest.method();
// then
assertEquas(enum, result.getCode())
}
}
I suspected that the input should be something other than any()
so I created a method that provides data to the test and used a @MethodSource annotation.
That method returns the arguments of the input to the mock and also expectedReturn from the mock.
@RunWith(MockitoJUnitRunner.class)
public class FooTest {
@Mocked
MockedObject mockedObject;
@InjectMocks
Foo underTest
@ParameterizedTest
@MethodSource("dataProvider")
public void test_ParametrizedTest(MockedInput mockedInput, Output expectedReturn) {
Output expectedReturn = Output.builder().code(enum).build();
// Given
when(mockedObject.method(mockedInput))
.thenReturn(expectedReturn);
// when
val result = underTest.method();
// then
assertEquas(enum, result.getCode())
}
private static Stream<Arguments> dataProvider() {
return Stream.of(
Arguments.of(mockedInput1, Output.builder().code(CodeEnum.S1).build()),
Arguments.of(mockedInput2, Output.builder().code(CodeEnum.S2).build())
)
}
}
How to make mocked objects return a parameter from a parametrized test?
Solution
The runner I was using was incorrect. I changed it to use MockitoExtension and the tests ran fine.
@ExtendWith(MockitoExtension.class)
public class FooTest {
@Mocked
MockedObject mockedObject;
@InjectMocks
Foo underTest
@ParameterizedTest
@MethodSource("dataProvider")
public void test_ParametrizedTest(MockedInput mockedInput, Output expectedReturn) {
Output expectedReturn = Output.builder().code(enum).build();
// Given
when(mockedObject.method(mockedInput))
.thenReturn(expectedReturn);
// when
val result = underTest.method();
// then
assertEquas(enum, result.getCode())
}
private static Stream<Arguments> dataProvider() {
return Stream.of(
Arguments.of(mockedInput1, Output.builder().code(CodeEnum.S1).build()),
Arguments.of(mockedInput2, Output.builder().code(CodeEnum.S2).build())
)
}
Answered By - PodGen4
Answer Checked By - Katrina (JavaFixing Volunteer)