Java 为什么在模拟TextView时会出现InvalidUseofMatcherException?
我有一组测试来验证我们Android应用程序中的一些功能。部分代码负责将某些字符串放入某些TextView。所以我想创建模拟TextView对象,以便在测试时使用:Java 为什么在模拟TextView时会出现InvalidUseofMatcherException?,java,android,unit-testing,textview,mockito,Java,Android,Unit Testing,Textview,Mockito,我有一组测试来验证我们Android应用程序中的一些功能。部分代码负责将某些字符串放入某些TextView。所以我想创建模拟TextView对象,以便在测试时使用: public static TextView getMockTextView() { TextView view = mock(TextView.class); final MutableObject<CharSequence> text = new MutableObject<CharSequen
public static TextView getMockTextView() {
TextView view = mock(TextView.class);
final MutableObject<CharSequence> text = new MutableObject<CharSequence>();
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
text.value = (CharSequence) invocation.getArguments()[0];
return null;
}
}).when(view).setText((CharSequence) any());
when(view.getText()).thenReturn(text.value);
return view;
}
我试过(CharSequence)any()
,(CharSequence)anyObject()
,甚至是anyString()
或eq(“”)
,只是想看看它是否有效,Mockito仍然不喜欢我尝试告诉它在setText()
的单参数版本中该怎么做
有什么想法吗?来自:
公共最终void setText(字符序列文本)
莫基托;Mockito生成的mock/spy类实际上是一个代理,但由于setText(CharSequence)
是final,因此JVM假设它知道调用哪个实现(TextView的真正实现),并且不参考代理(Mockito实现),因为虚拟方法调度将指示它。大概setText(CharSequence)
的实现实际上调用了setText(CharSequence,BufferType)
,Mockito假设这是您想要模拟的调用,因此它会给您错误消息“预期2个匹配器,1个已记录”。(第二个匹配器将用于BufferType。)
您需要执行以下操作之一:
- 使用,它使用一个特殊的类加载器在测试中用可用的等价物替换Android类
- 使用,它还使用一个特殊的类加载器重写被测系统,以便即使在调用final方法时也将其委托给mock(以及许多其他添加的特性)
- 完全跳过使用模拟,使用真实对象或编写完全可模拟的包装层
anyVararg()
,而是你在模仿;最好模拟setText(any(CharSequence.class)、any(BufferType.class))
。请小心,它仍然非常脆弱,因为您依赖的假设是setText(CharSequence)
调用setText(CharSequence,BufferType)
并且没有做很多其他事情,在一个实现中您无法控制。是的。(如果异常只告诉我错误是什么,我会节省一半的时间:)
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at com.me.util.MockViewHelper.getMockTextView(MockViewHelper.java:49)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.