RecyclerView适配器在单元测试中的应用

4
如何在Android Studio中运行单元测试时测试支持库类? 根据http://tools.android.com/tech-docs/unit-testing-support上的介绍,它与默认的Android类一起工作:

单元测试在开发机器上的本地JVM上运行。我们的gradle插件将编译src/test/java中找到的源代码,并使用通常的Gradle测试机制执行它。在运行时,测试将针对已剥离所有final修饰符的android.jar的修改版本执行。这使您可以使用流行的模拟库,如Mockito。

但是,当我尝试在RecyclerView适配器上使用Mockito时,如下所示:

@Before
public void setUp() throws Exception {
    adapter = mock(MyAdapterAdapter.class);
    when(adapter.hasStableIds()).thenReturn(true);
}

那么我将收到错误信息:
org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
   It is a limitation of the mock engine.

原因是支持库没有提供一个"去掉所有final修饰符的jar文件"。

那怎么测试呢?也许通过子类化和重写final方法(这并不起作用,所以不行)。也许需要使用PowerMock?


请查看我的测试:https://github.com/jaredsburrows/AndroidGradleTemplate/blob/master/Example-AllLibraries/src/test/java/burrows/apps/example/template/adapter/BaseAdapterTest.java - Jared Burrows
@JaredBurrows 我看到您在2016年8月28日的提交7ebf6a36911cc中删除了这个测试。测试有问题吗? - Stef
你有提交的链接吗? - Jared Burrows
@JaredBurrows:当然可以:https://github.com/jaredsburrows/android-gradle-java-app-template/commit/7ebf6a36911cc - Stef
2个回答

2

PowerMockito 解决方案

步骤 1: 从https://code.google.com/p/powermock/wiki/MockitoUsage13中找到正确的 Mockito & PowerMock 版本,并将其添加到 build.gradle 中:

testCompile 'org.powermock:powermock-module-junit4:1.6.1'
testCompile 'org.powermock:powermock-api-mockito:1.6.1'
testCompile "org.mockito:mockito-core:1.10.8"

仅在一起更新,并根据使用页面进行更新。

步骤2: 设置单元测试类,准备目标类(包含最终方法):

@RunWith(PowerMockRunner.class)
@PrepareForTest( { MyAdapterAdapter.class })
public class AdapterTrackerTest {

第三步: 将Mockito...方法替换为PowerMockito:
adapter = PowerMockito.mock(PhotosHomeAlbumsAdapter.class);
PowerMockito.when(adapter.hasStableIds()).thenReturn(true);

为什么要使用 PowerMockito 而不是 Mockito - Jared Burrows
主要是因为hasStableIds()被声明为final - Sebastian Roth
Mockito自2.1.0版本开始支持模拟final方法。 - Oren Bochman

0
@Before
public void setUp() throws Exception {
    adapter = mock(MyAdapterAdapter.class);
    when(adapter.hasStableIds()).thenReturn(true);
}

编译器无法解释 "when" 关键字。您可以在 Java 中使用 "Mockito.when" 或在 Kotlin 中使用 Mockito.when。由于关键字 "when" 已经存在于 Kotlin 语言中,所以需要使用这些撇号。但是,您也可以使用 whenever 替代 Mockito.when

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接