Mockito - 覆盖采用原始参数的方法

时间:2013-09-22 07:41:16

标签: java android unit-testing mockito

我有一个类,它是Context的子类。我对另一个依赖于这门课程的班级进行单元测试,因此我嘲笑它。但是,我需要一些方法来充当他们的原始行为,所以我要去" unmock"它们。

其中一个是getAssets()所以我写了这个并且它正常工作:

Mockito.doReturn(this.getContext().getAssets()).when(keyboard).getAssets();

keyboard是所提到的类的模拟实例。

由于此方法不带参数,因此覆盖它非常简单。

我也需要覆盖Context.getString(int)。该参数使事情变得困难,而且它是一个原始的,使得更加困难。

我拿了this advice和另一个,并尝试编写此代码:

Mockito.when(keyboard.getString(Mockito.anyInt())).thenAnswer(new Answer<String>(){
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable
         Integer arg = (Integer)invocation.getArguments()[0];
         return OuterClass.this.getContext().getString(arg.intValue());
    }
});

编译并执行,但出现以下异常:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at [...] <The code above>

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.

at android.content.Context.getString(Context.java:282)
at [...]
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:545)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551)

所以主要的问题是如何覆盖Mockito中的方法,它们具有原始参数?

提前致谢

3 个答案:

答案 0 :(得分:3)

你不能存根getString,因为它是最终的。 Mockito不能存在最终方法。只需将其保留为未打印状态,即可获得原始实现。这就是你想要的,对吧?

答案 1 :(得分:1)

不应该是Answer<String>吗?

Mockito.when(keyboard.getString(Mockito.anyInt())).thenAnswer(new Answer<String>(){
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
         return "foo";
    }
});

你可以重命名键盘 - &gt; mockContext,那会更清楚吗?

答案 2 :(得分:0)

David Wallace中注明his answerContext.getString()方法是最终的,我们知道mockito无法模拟最终方法。所以压倒它也是一个坏主意,也不会起作用。

关于"0 matchers expected, 1 recorded"描述的InvalidUseOfMatchersException信息是一种模糊的方式,表示该方法为final,我们不得试图覆盖它。

然而,保留它不会有帮助,因为该对象仍然是一个模拟对象,并且该方法不会显示我们想要的普通对象的预期行为;所以这个选项也不在桌面上。

最后我决定改变并改进我的设计。我使用Interface segregation principle并将ContextKeyboard的职责分开(我正在开发IME服务)。在应用程序本身中,我为这两个传递了keyboard的相同对象,但在测试中我嘲笑Keyboard没有任何不良副作用,并使用TestCase.getContext()作为Context这消除了“取消”其方法的必要性。