2015-01-14 4 views
4

Я попытался использовать PowerMock с Robolectric, чтобы издеваться над статическим методом в моем проекте Android. Я использую град. Но я получаю следующее исключение:Не могу использовать PowerMock с Robolectric и Gradle (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

Я использовал этот пост, чтобы попытаться заставить его работать (используя упомянутые там библиотеки), но он пока не работает. Я чувствую, что это какая-то проблема с градиентом и андроидом. – 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 и Mockito 2.

Очевидно, что при запуске Robolectric с уровнем API уровня 21 в рабочем варианте java отсутствует один класс.

Если кто-то сталкивается с подобной проблемой, это руководство показывает полный рабочий пример со всеми зависимостями и настройки: https://github.com/robolectric/robolectric/wiki/Using-PowerMock

Смежные вопросы