如何在Android项目中使用PowerMock?

16

我创建了一个新的Android测试项目。我从https://code.google.com/p/powermock/downloads/list下载了powermock-mockito-junit-1-1.5.zip文件。我将所有库添加到测试项目的libs文件夹中。测试类是一个非常简单的对象:

package com.test.test;

import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;

import android.util.Log;

@RunWith(PowerMockRunner.class)
public class TestTestAndroid {

    public void testRuns() {
        Log.e("test", "Test case is called");
    }
}

然后,我尝试从Eclipse运行项目或从命令行制作项目。结果我得到了相同的错误:

Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lorg/hamcrest/Description;

事实证明,junit-4.8.2.jarmockito-all-1.9.5.jar都定义了org.hamcrest.Description。显然,我必须包含Mockito jar - 我需要Mockito。 Android提供了一个不同版本的JUnit,但它是一个旧版本,不包括@RunWith注释。

有人能回答如何在Android项目中使用PowerMock和Mockito,而不会出现冲突的org.hamcrest.Description问题吗?

2个回答

13

抱歉,您无法在Dalvik VM中使用PowerMock。

PowerMock通过在自定义ClassLoader下运行您的测试来修改类的字节码,使用Javassist。这在普通的JVM上可以正常工作,但在Dalvik上,字节码和类格式是不同的,所以这种方法不起作用。 PowerMock需要重新编写以使用Dexmaker而不是Javassist-这将是非常困难的,并且我在PowerMock issues list中没有看到类似的内容。


如果你无法在Android上使用PowerMock,你知道其他方法来存根Android上的静态方法吗? - lowellk
7
有一个解决方法。可以编写一个非静态的方法去调用这个静态方法,然后再进行存根处理。例如,如果 HttpConstants.getUrl() 是一个静态方法,那么编写另一个方法:String getUrl() { return HttpConstants.getUrl(); },然后你就可以对这个方法进行存根处理了。 - Matt Quigley

12

实际上,我发现这完全不是真的(至少对于最新版本而言)。

在我的Gradle设置中,我针对我想测试代码的模块有以下配置:

// Mockito and PowerMock
androidTestCompile ('org.powermock:powermock-mockito-release-full:1.6.0') {
    exclude module: 'hamcrest-core'
    exclude module: 'objenesis'
}

一切都运行良好。只要我使用:

@RunWith(PowerMockRunner.class) @PrepareForTest(ClassToMock.class)

为我的类添加注释(例如,无法在Robolectric中运行,但在CI环境中仍然可以正常运行)


1
你能发布你的完整Gradle设置吗?我找不到PowerMockRunner.class的导入。 - Sandro Machado
很抱歉,我不能提供您所需的内容,因为它是我们公司应用程序的一部分,但它应该通过导入import org.powermock.modules.junit4.PowerMockRunner;存在于其中。只需确保如果您正在使用 androidTestCompile,则使用此导入的仪器测试位于 androidTest 文件夹中等等。 - AllDayAmazing
好的,但是为了导入它,我需要在gradle中编译以下内容: androidTestCompile 'org.powermock:powermock-module-junit4:1.6.2' 这给我带来了很多问题,比如:“Multiple dex files defined…” - Sandro Machado
听起来好像达到了short int的限制,所以您可能需要使用multidex启用或者只需在命令行中在项目根目录下使用gradle -q app:dependencies检查您的文件,看看有哪些导入重叠。此外,请注意powermock-mockito-release-full导入包含Mockito,因此您不需要同时导入两个。 - AllDayAmazing
当我使用PowerMockRunner进行注释时,我会得到异常'I/TestRunner: java.lang.IllegalStateException: Extension API internal error: org.powermock.api.extension.proxyframework.ProxyFrameworkImpl无法在类路径中找到。',有其他人也遇到这个问题吗? - Faux Pas
显示剩余2条评论

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