Mockito returnsFirstArg()不适用于通用的第一个arg

tro*_*oig 5 java mocking matcher mockito powermock

编辑:我终于在mockito github项目上创建了一个问题.

我正在尝试使用Mockito 功能模拟getNameElementInterface 的类型化方法RoomGeneralService以返回第一个arg AdditionalAnswers.returnsFirstArg:

模拟界面:

interface PrimaryKeyElement<T> {
   public String getNameElement(T primaryKey);
}

interface RoomGeneralService extends PrimaryKeyElement<String> {
   // ...
}
Run Code Online (Sandbox Code Playgroud)

我的测试(注意进口)

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());
      //...
   }
}
Run Code Online (Sandbox Code Playgroud)

我也试过其他组合,但到目前为止没有成功:

when(roomGeneralService.getNameElement(Matchers.<String>any())).thenAnswer(returnsFirstArg());
doAnswer(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
doReturn(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
Run Code Online (Sandbox Code Playgroud)

收到错误:

出现此错误的原因可能是:1.想要的参数位置不正确.答案用于错误的互动.

有用参数的位置为0,此方法的可能参数索引为:[0]对象

解决方法:

我知道我可以创建自己的答案,事实上,如果不使用returnFirstArg()我做这样的事情,它工作正常:

when(roomGeneralService.getNameElement(anyString())).thenAnswer(new Answer<String>() {
   @Override
   public String answer(InvocationOnMock invocation) throws Throwable {
      return (String) invocation.getArguments()[0];
   }
});
Run Code Online (Sandbox Code Playgroud)

但是我会returnFirstArg()在其余的测试中使用(测试看起来更干净),并且如果方法getNameElement将接收到String一个Targ,则模拟工作正常.

谢谢您的帮助.

tro*_*oig 0

我最终决定在mockito github项目上提出一个问题(#1071),并已在2.8.29版本中修复(请参阅官方更新日志)感谢Mockito团队如此迅速地解决了它!

引用@ChristianSchwarz,这是一个问题解释:

Mockito 检查参数类型是否与返回类型兼容,以便尽快发现 API 的误用。在这种情况下,由于类型擦除,参数类型 Object 是从泛型类型 T 推断出来的。由于 Object 不是 String 的子类型,Mockito 会抛出您看到的异常。

解决方案:可以通过推断实际参数实例的参数类型来解决该问题。如果参数类型是原语或 arg 为 null,Mockito 必须回退并使用方法签名提供的类型。