为什么我得到InvalidUseOfMatchersException时嘲笑TextView



我有一组测试来验证我们Android应用程序中的一些功能。部分代码负责将某些字符串放入某些TextView中。所以我想创建模拟TextView对象时使用测试:

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;
}

这适用于2参数setText(CharSequence, BufferType)…然而,我们的大部分代码只调用setText(CharSequence),所以我也想在这种情况下捕获字符串(正如你在上面的代码中看到的)。

但是我得到了这个异常:

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.

我试过(CharSequence)any(), (CharSequence)anyObject(),甚至anyString()eq("")只是为了看看它是否会起作用,Mockito仍然不喜欢我试图告诉它在setText()的1参数版本中做什么。

你知道这是怎么回事吗?

From TextView docs:

public final void setText (CharSequence text)

Mockito不能模拟final方法;Mockito生成的mock/spy类实际上是一个代理,但是由于setText(CharSequence)是final的,JVM假设它知道调用哪个实现(TextView的实际实现),并且不像虚拟方法调度所指示的那样咨询代理(Mockito实现)。假设setText(CharSequence)的实现实际上调用了setText(CharSequence, BufferType), Mockito假设这是您想要模拟的调用,因此它会给您错误消息"预期2个匹配器,记录1个"。(第二个匹配器将用于BufferType。)

你需要做以下其中一项:

  • 使用Robolectric,它使用一个特殊的类加载器在测试中用可工作的等效类替换Android类。
  • 使用PowerMock,它还使用一个特殊的类加载器来重写被测系统,甚至在调用final方法时(以及许多其他添加的功能)也可以委托给mock。
  • 完全跳过模拟,使用一个真实的对象或编写一个完全可模拟的包装层。

相关内容

  • 没有找到相关文章

最新更新