Mockito returnsFirstArg() 不适用于通用的第一个参数
Mockito returnsFirstArg() doesn't work with generic first arg
EDIT: I've finally created an issue on mockito github project.
我正在尝试使用 Mockito AdditionalAnswers.returnsFirstArg
功能将接口 RoomGeneralService
的类型化方法 getNameElement
模拟为 return 第一个参数:
模拟接口:
interface PrimaryKeyElement<T> {
public String getNameElement(T primaryKey);
}
interface RoomGeneralService extends PrimaryKeyElement<String> {
// ...
}
我的测试(注意进口)
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());
//...
}
}
我也尝试过其他组合,但到目前为止没有成功:
when(roomGeneralService.getNameElement(Matchers.<String>any())).thenAnswer(returnsFirstArg());
doAnswer(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
doReturn(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
收到错误:
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
解决方法:
我知道我可以创建自己的答案,事实上,如果不使用 returnFirstArg()
我会这样做,它工作正常:
when(roomGeneralService.getNameElement(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return (String) invocation.getArguments()[0];
}
});
但我会像在我的其余测试中一样使用 returnFirstArg()
(测试看起来更干净),并且如果方法 getNameElement
会收到 String
,模拟工作正常取而代之的是 T
arg.
感谢您的帮助。
Mockito 似乎不够聪明,无法推断参数类型将绑定到参数化子接口中的 String
。
您可以覆盖子接口中的方法
interface RoomGeneralService extends PrimaryKeyElement<String> {
@Override
public String getNameElement(String primaryKey);
}
Mockito 无需猜测。它会清楚地看到 String
作为存根方法的参数类型。
终于决定开issue了(#1071) on mockito github project and it has been fixed in version 2.8.29 (See the official changelog)感谢Mockito团队这么快就解决了!
引用@ChristianSchwarz,这里有一个问题解释:
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.
EDIT: I've finally created an issue on mockito github project.
我正在尝试使用 Mockito AdditionalAnswers.returnsFirstArg
功能将接口 RoomGeneralService
的类型化方法 getNameElement
模拟为 return 第一个参数:
模拟接口:
interface PrimaryKeyElement<T> {
public String getNameElement(T primaryKey);
}
interface RoomGeneralService extends PrimaryKeyElement<String> {
// ...
}
我的测试(注意进口)
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());
//...
}
}
我也尝试过其他组合,但到目前为止没有成功:
when(roomGeneralService.getNameElement(Matchers.<String>any())).thenAnswer(returnsFirstArg());
doAnswer(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
doReturn(returnsFirstArg()).when(roomGeneralService.getNameElement(anyString()));
收到错误:
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
解决方法:
我知道我可以创建自己的答案,事实上,如果不使用 returnFirstArg()
我会这样做,它工作正常:
when(roomGeneralService.getNameElement(anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return (String) invocation.getArguments()[0];
}
});
但我会像在我的其余测试中一样使用 returnFirstArg()
(测试看起来更干净),并且如果方法 getNameElement
会收到 String
,模拟工作正常取而代之的是 T
arg.
感谢您的帮助。
Mockito 似乎不够聪明,无法推断参数类型将绑定到参数化子接口中的 String
。
您可以覆盖子接口中的方法
interface RoomGeneralService extends PrimaryKeyElement<String> {
@Override
public String getNameElement(String primaryKey);
}
Mockito 无需猜测。它会清楚地看到 String
作为存根方法的参数类型。
终于决定开issue了(#1071) on mockito github project and it has been fixed in version 2.8.29 (See the official changelog)感谢Mockito团队这么快就解决了!
引用@ChristianSchwarz,这里有一个问题解释:
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.