2015-01-14 83 views
4

我试图使用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单元测试?任何想法我可能做错了什么?

+1

[使用PowerMock和Robolectric - IncompatibleClassChangeError]的可能重复(http://stackoverflow.com/问题/ 20557769/using-powermock-and-robolectric-incompatibleclasschangeerror) –

+0

我使用这篇文章试图让它工作(使用那里提到的库),但它不工作。我觉得这是一些Gradle和Android问题。 – vetho

+0

请显示整个build.gradle文件 –

回答

2

我创建了一个example project其中集成Robolectric 3 + RobolectricGradleTestRunner + PowerMock + Mockito

build.gradle

dependencies { 

    ... 

    testCompile "org.powermock:powermock-module-junit4:1.6.2" 
    testCompile "org.powermock:powermock-module-junit4-rule:1.6.2" 
    testCompile "org.powermock:powermock-api-mockito:1.6.2" 
    testCompile "org.powermock:powermock-classloading-xstream:1.6.2" 
} 

测试类:

@RunWith(RobolectricGradleTestRunner.class) 
@Config(constants = BuildConfig.class, sdk = 18) 
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" }) 
@PrepareForTest(Static.class) 
public class DeckardActivityTest { 

    @Rule 
    public PowerMockRule rule = new PowerMockRule(); 

    @Test 
    public void testStaticMocking() { 
     PowerMockito.mockStatic(Static.class); 
     Mockito.when(Static.staticMethod()).thenReturn("hello mock"); 

     assertTrue(Static.staticMethod().equals("hello mock")); 
    } 
} 
0

上面的答案对我帮助很大,但我仍然无法得到它与Robelolectric 3和2的Mockito

运行显然,在运行API级别为21的Robolectric时,桌面java版本中缺少一个类。

如果有人正面临着类似的问题还有,本指南显示了所有的依赖关系,并建立一个完整的工作示例:https://github.com/robolectric/robolectric/wiki/Using-PowerMock

相关问题