我試圖使用PowerMock和Robolectric來模擬我的android項目中的靜態方法。我正在使用gradle。但我收到以下異常:不能在Robolectric和Gradle中使用PowerMock(android)
Caused by: java.lang.IllegalStateException: PowerMockRule can only be used with the system classloader but was loaded by [email protected]
at org.powermock.modules.junit4.rule.PowerMockRule.<clinit>(PowerMockRule.java:35)
... 47 more
我的測試類看起來像這樣:
...
import org.junit.Rule;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.powermock.modules.agent.PowerMockAgent;
import org.powermock.core.classloader.annotations.*;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.rule.PowerMockRule;
@RunWith(RobolectricTestRunner.class)
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" })
@Config(manifest = "./src/main/AndroidManifest.xml",emulateSdk = 18)
public class MyTest {
@Rule
public PowerMockRule rule = new PowerMockRule();
@Test
public void test() {
...
}
}
完整gradle這個文件(有些真的不相關的東西被刪除):
apply plugin: 'com.android.application'
String[][] allowedFlavorCombinations = [
...
];
android.variantFilter { variant ->
boolean buildVariant = false;
for (int i = 0; i < allowedFlavorCombinations.length; i++) {
if(allowedFlavorCombinations[i][0].equalsIgnoreCase(variant.getFlavors().get(0).name)
&& allowedFlavorCombinations[i][1].equalsIgnoreCase(variant.getFlavors().get(1).name)) {
buildVariant = true;
}
}
variant.setIgnore(!buildVariant);
}
android {
compileSdkVersion 20
buildToolsVersion "20"
defaultConfig {
minSdkVersion 11
targetSdkVersion 20
versionCode=139
versionName="3.0"
}
sourceSets {
instrumentTest.setRoot('src/test')
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
signingConfigs {
release
}
buildTypes {
release {
minifyEnabled false
signingConfig signingConfigs.release
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(output.outputFile.parent, output.outputFile.name.replace(".apk", "-" + defaultConfig.versionName + ".apk"))
}
}
}
}
if (project.hasProperty('storeFile') &&
project.hasProperty('storePassword') &&
project.hasProperty('keyPassword')) {
android.signingConfigs.release.storeFile = file(storeFile)
android.signingConfigs.release.storePassword = storePassword
android.signingConfigs.release.keyPassword = keyPassword
android.signingConfigs.release.keyAlias = keyAlias
} else {
buildTypes.release.signingConfig = null
}
flavorDimensions "client", "settings"
productFlavors {
...
}
}
sourceSets {
unitTest {
java.srcDir file('src/test/java')
resources.srcDir file('src/test/res')
}
}
configurations {
unitTestCompile.extendsFrom runtime
unitTestRuntime.extendsFrom unitTestCompile
}
dependencies {
compile 'com.android.support:appcompat-v7:20.0.0'
compile 'com.android.support:recyclerview-v7:21.0.0'
compile 'com.google.code.gson:gson:2.3'
compile 'com.google.android.gms:play-services:6.1.71'
compile 'com.android.support:support-v4:21.0.0'
compile 'com.nineoldandroids:library:2.4.0'
compile 'com.android.support:gridlayout-v7:21.0.+'
compile fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
unitTestCompile files("$project.buildDir/intermediates/classes/testbase/debug/")
...
unitTestCompile 'junit:junit:4.11'
unitTestCompile 'com.loopj.android:android-async-http:1.4.6'
unitTestCompile('org.robolectric:robolectric:2.3:jar-with-dependencies') {
exclude module: 'support-v4'
}
unitTestCompile 'com.google.android:android:4.1.1.4'
unitTestCompile 'org.mockito:mockito-core:1.10.8'
unitTestCompile 'org.powermock:powermock-api-mockito:1.6.1'
unitTestCompile 'org.powermock:powermock-module-junit4-rule-agent:1.6.1'
unitTestCompile 'org.powermock:powermock-module-junit4-rule:1.6.1'
unitTestCompile 'org.powermock:powermock-module-junit4:1.6.1'
unitTestCompile 'com.android.support:appcompat-v7:20.0.0'
unitTestCompile 'com.google.code.gson:gson:2.3'
unitTestCompile 'com.google.android.gms:play-services:6.1.71'
unitTestCompile 'com.android.support:support-v4:21.0.0'
unitTestCompile 'joda-time:joda-time:2.5'
unitTestCompile fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
instrumentTestCompile 'junit:junit:4.11'
instrumentTestCompile('org.robolectric:robolectric:2.3:jar-with-dependencies') {
exclude module: 'support-v4'
}
}
task unitTest(type:Test, dependsOn: [assembleDefault, ':AndroidUtilitiesLibrary:unitTest', ':AndroidUraLibrary:unitTest']) {
testClassesDir = project.sourceSets.unitTest.output.classesDir
classpath = project.sourceSets.unitTest.runtimeClasspath
}
check.dependsOn unitTest
另外還有一個頂級構建文件(因爲我們有幾個模塊)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'
}
}
subprojects {
apply plugin: 'android-sdk-manager'
}
allprojects {
repositories {
jcenter()
}
}
有沒有人使用Powermockito進行基於Robolectric的Android單元測試?任何想法我可能做錯了什麼?
[使用PowerMock和Robolectric - IncompatibleClassChangeError]的可能重複(http://stackoverflow.com/問題/ 20557769/using-powermock-and-robolectric-incompatibleclasschangeerror) –
我使用這篇文章試圖讓它工作(使用那裏提到的庫),但它不工作。我覺得這是一些Gradle和Android問題。 – vetho
請顯示整個build.gradle文件 –