Mockito returnsFirstArg () does not work with the common first argument arg

EDIT : I finally created the issue mickito github project.

I'm trying to make fun of the typed getNameElement method of the getNameElement interface to return the first arg using the Mockito AdditionalAnswers.returnsFirstArg functionality:

Interface for layout :

 interface PrimaryKeyElement<T> { public String getNameElement(T primaryKey); } interface RoomGeneralService extends PrimaryKeyElement<String> { // ... } 

My test (pay attention to import)

 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()); //... } } 

I also tried with other combinations, but without success:

 when(roomGeneralService.getNameElement(Matchers.<String>any())).thenAnswer(returnsFirstArg()); doAnswer(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString())); doReturn(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString())); 

Received error :

The cause of this error may be: 1. The desired position of the argument is incorrect. 2. The answer is used for incorrect interaction.

The position of the desired argument is 0, and the possible argument arguments for this method are: [0] Object

Bypass

I know that I can create my own answer, and actually it works fine if, instead of using 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 my other tests (the tests look cleaner), and the mockery works fine if the getNameElement method gets a String instead of a T arg.

Thanks for the help.

+5
source share
2 answers

Finally, I decided to open the problem ( # 1071 ) in the mockito github project and was fixed in version 2.8. 29 (see Official Change Log ) Thanks to the Mockito team, it can be quickly resolved!

Quote from @ChristianSchwarz, here is a description of the problem:

Mockito checks to see if the argument type is compatible with the return type to make an incorrect use of the API as soon as it becomes visible. In this case, an object of type argument is inferred from the general type T, due to the type of erasure. Since Object is not a subtype of String Mockito throws the exception you see.

Solution: The problem can be fixed by outputting the argument-type of the actual argument-instance. If the type argument is primitive or arg is null, Mockito should backtrack and use the type provided by the method signature.

0
source

It seems that Mockito is not smart enough to infer that the type of the parameter will be bound to String in the parameterized subinterface.

You can override the method in the subinterface

 interface RoomGeneralService extends PrimaryKeyElement<String> { @Override public String getNameElement(String primaryKey); } 

Mokito will not have to guess. He will clearly see String as the parameter type of the hatched method.

+1
source

All Articles