EDIT: I've finally created an issue on mockito github project.
I'm trying to mock the typed method getNameElement
of Interface RoomGeneralService
to return the first arg, using Mockito AdditionalAnswers.returnsFirstArg
functionality:
Interface to mock:
interface PrimaryKeyElement<T> {
public String getNameElement(T primaryKey);
}
interface RoomGeneralService extends PrimaryKeyElement<String> {
// ...
}
My test (note the imports)
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
public class SampleTest {
@Mock
RoomGeneralService roomGeneralService;
@Test
public void testFoo() throws Exception {
when(roomGeneralService.getNameElement(anyString())).thenAnswer(returnsFirstArg());
//...
}
}
Also I've tried with other combinations, but without success so far:
when(roomGeneralService.getNameElement(Matchers.<String>any())).thenAnswer(returnsFirstArg());
doAnswer(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
doReturn(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
Error received:
The reason for this error can be : 1. The wanted argument position is incorrect. 2. The answer is used on the wrong interaction.
Position of the wanted argument is 0 and the possible argument indexes for this method are : [0] Object
Workaround:
I know I can create my own answer, and in fact it's working fine if instead of use returnFirstArg()
I do something like this:
when(roomGeneralService.getNameElement(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return (String) invocation.getArguments()[0];
}
});
But I would use returnFirstArg()
as in the rest of my tests (tests look cleaner), as well as mocking is working fine if the method getNameElement
would receive an String
instead a T
arg.
Thanks for the help.
I finally decided to open an issue (#1071) on mockito github project and it has been fixed in version 2.8.29 (See the official changelog) Thanks to the Mockito team to solve it so quickly!
Quoting @ChristianSchwarz, here is a problem explanation:
Mockito checks if the argument type is compatible with the return type to make a misuse ot the API as soon as posible visible. In this case the argument-type Object is inferred from the generic type T, due to type erasure. Since Object is not a subtype of String Mockito throws the exception you see.
Solution: The issue can by fixed by inferring the argument-type of the actual argument-instance. In case the argument-type is a primitive or the arg is null Mockito must fallback and use the type provided by method signature.