5

ogni volta che eseguo un test di unità, ottengo questo errore quando tenta di recuperare un valore di stringa da un file config.xml personalizzato.

Background:

Il progetto stesso è un progetto apk libreria che utilizza e riferimenti un altro progetto APK biblioteca.

L'errore si verifica quando il progetto stesso tenta di avviare un nuovo oggetto che è una sottoclasse di una super classe contenuta nel progetto apk della libreria di riferimento.

Problema spiegato più sotto

La specifica linea di codice che con l'errore è una variabile statica definito di seguito:

protected static final String ANDROID_CONFIG_ID = LibraryApplication.getApplication().getString(R.string.api_checkout_config_id_override); 

non riesce con il seguente errore:

java.lang.NoClassDefFoundError: com/jon/commonlib/R$string 

commonLib è l'apk della libreria di riferimento se vi state chiedendo.

Ecco il mio test di unità

@RunWith(RobolectricTestRunner.class) 
@Config(constants = BuildConfig.class, manifest=Config.NONE) 
public class TestSearchShows { 

    @Test 
    public void testSearchJsonFile(){ 
     EventsTestHelper testHelper = new EventsTestHelper(RuntimeEnvironment.application); 

     try { 
      ShowsList showList = testHelper.getShowList(new SearchEvent()); 

      if(showList.getShows().size() < 0){ 
       Assert.fail("show list is empty"); 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
      Assert.fail(e.toString()); 
     } 
    } 


} 

L'EventsTestHelper è la classe secondaria per una classe super-chiamato NetworkHelper che assomiglia a questo:

public abstract class NetworkHelper<T, P, S> implements NetworkConstants { 

protected static final String ANDROID_CONFIG_ID = LibraryApplication.getApplication().getString(R.string.api_checkout_config_id_override); 

//other stuff .... 

} 

Io uso robolectric versione 3.0 il più recente per correndo, i miei test unitari.

Se mi è stato per eseguire il codice dal vivo e chiamare e avviare la classe secondaria, funziona perfettamente bene, non si blocca

Modifica: Ecco frammenti della mia build file Gradle sotto

apply plugin: 'android-sdk-manager' 
apply plugin: 'com.android.library' 
apply plugin: 'crashlytics' 


buildscript { 
    repositories { 
     jcenter() 
     mavenCentral() 
     maven { url 'http://download.crashlytics.com/maven' } 
     maven { url 'http://www.testfairy.com/maven' } 

    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:1.1.0' 
     classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.+' 
     classpath 'com.crashlytics.tools.gradle:crashlytics-gradle:1.+' 
     classpath 'com.testfairy.plugins.gradle:testfairy:1.+' 

    } 
} 

repositories { 
    mavenCentral() 
    maven { url 'http://download.crashlytics.com/maven' } 
    maven { url "https://oss.sonatype.org/content/repositories/snapshots" } 
    flatDir { 
     dirs 'libs' 
    } 
} 

android { 
    compileSdkVersion 19 
    buildToolsVersion "22.0.1" 
    def package_namespace = "com.jonney.moduleApp" 

    defaultConfig { 
     minSdkVersion 14 
     testApplicationId "com.jonney.moduleApp" 
     targetSdkVersion 19 
     versionCode 1 
     versionName "1.0" 
    } 
productFlavors { 
     //testing { 
     //} 
     local { 
     } 
     mock { 
     } 
     qa { 
     } 
     //qa4 { 
     //} 
     production { 
     } 
    } 

    sourceSets { 



     local { 
      res.srcDir 'build-config/local/res' 
     } 
     testing { 
      res.srcDir 'build-config/testing/res' 
     } 
     mock { 
      res.srcDir 'build-config/mock/res' 
     } 
     qa { 
      res.srcDir 'build-config/qa/res' 
     } 
     qa4 { 
      res.srcDir 'build-config/qa4/res' 
     } 
     staging { 
      res.srcDir 'build-config/staging/res' 
      test.java.srcDirs += 'src/main/java' 
     } 
     production { 
      res.srcDir 'build-config/production/res' 
      test.java.srcDirs += 'src/main/java' 
      test.java.srcDirs += "build/generated/source/r/production" 
      test.java.srcDirs += "build/generated/source/buildConfig/production" 
     } 

    } 
} 

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    compile 'com.android.support:appcompat-v7:19.1.+' 
    compile 'com.google.code.gson:gson:2.3' 
    testCompile('org.robolectric:robolectric:3.0') { 
     exclude group: 'commons-logging', module: 'commons-logging' 
     exclude group: 'org.apache.httpcomponents', module: 'httpclient' 
    } 
    compile 'com.fasterxml.jackson:jackson-parent:2.5' 
    compile 'com.squareup:otto:1.3.6' 
    compile 'com.jakewharton:butterknife:6.1.0' 
    compile 'com.sothree.slidinguppanel:library:3.0.0' 
    compile 'com.crashlytics.android:crashlytics:1.+' 
    compile 'com.mcxiaoke.volley:library-aar:1.0.0' 
    compile "joda-time:joda-time:2.4" 
    testCompile('junit:junit:4.12') { 
     exclude module: 'hamcrest' 
     exclude module: 'hamcrest-core' 
    } 
    testCompile 'org.hamcrest:hamcrest-all:1.3' 
    compile 'com.sothree.slidinguppanel:library:3.0.0' 
    compile 'com.squareup:otto:1.3.6' 
    compile 'com.squareup.okhttp:okhttp:2.3.0' 
    testCompile 'org.apache.maven:maven-ant-tasks:2.1.3' 

    compile 'com.google.android.gms:play-services:7.0.0' 

    compile 'com.android.support:multidex:1.0.0' 

    compile(name: 'commonLib 1.0 1', ext: 'aar') 
    testCompile(name: 'commonLib-1.0 1', ext: 'aar') 
} 

modifica : ho anche provato a creare manualmente un'attività che copia la classe r per ciascuna dipendenza.

afterEvaluate { project -> 
     android.libraryVariants.each { variant -> 
      // workaround for missing R class for aar dependencies 
      def copyTaskName = "copy${variant.name.capitalize()}AppCompat" 
      def copyTaskNameTwo = "copy${variant.name.capitalize()}commonlib" 
      task(copyTaskName, type:Copy) { 
       dependsOn "process${variant.name.capitalize()}Resources" 
       from { "build/generated/source/r/${variant.dirName}/$package_namespace_path" } 
       into { "build/generated/source/r/${variant.dirName}/com/jon/commonlib" } 
//    into { "src/test/java/android/support/v7/appcompat" } 
       include 'R.java' 
       filter { line -> line.contains("package ${package_namespace};") ? 'package android.support.v7.appcompat;' : line } 
       outputs.upToDateWhen { false } 
      } 
      task(copyTaskNameTwo, type:Copy) { 
       dependsOn "process${variant.name.capitalize()}Resources" 
       from { "build/generated/source/r/${variant.dirName}/$package_namespace_path" } 
       into { "build/generated/source/r/${variant.dirName}/android/support/v7/appcompat" } 
//    into { "src/test/java/android/support/v7/appcompat" } 
       include 'R.java' 
       filter { line -> line.contains("package ${package_namespace};") ? 'package com.jon.commonlib;' : line } 
       outputs.upToDateWhen { false } 
      } 
      System.out.println("adding ${copyTaskName} build/generated/source/r/${variant.dirName}/$package_namespace_path ") 
      println("basename = ${variant.baseName}") 
      println("directory name = ${variant.dirName}") 
      tasks.getByName("compile${variant.name.capitalize()}UnitTestJava") dependsOn copyTaskName 
     } 
    } 

Cordiali saluti

jonnney

+0

potrebbe anche condividere il file build.gradle? –

+0

ciao ho aggiunto il file di build. grazie – jonney

risposta

0

Stai compresa la biblioteca nel classpath il test?

dependencies { 
    androidTestCompile(<reference to commonLib>) 
} 
+0

lo ho come compile () proverò il tuo suggerimento – jonney

+0

Ok si ora ho aggiunto la dipendenza adizionale e ho lo stesso errore. ecco cosa ho aggiunto compile (nome: 'commonlib-production-release-1.0 1', ext: 'aar') testCompile (nome: 'commonlib-production-release-1.0 1', ext: 'aar ') – jonney

+0

NoClassDefFoundError indica che il progetto di test non è a conoscenza della libreria di supporto. Sto anche partendo dal presupposto che il tuo file build.gradle sia compilato da quando hai detto che hai specificato tramite 'testCompile' - che mi dice che hai un tipo di build _test_ per il test delle unità. – zec

-2

La libreria potrebbe essere in conflitto con qualche altra libreria, quindi provare a risolvere il conflitto potrebbe essere il problema.

0

Non ero in grado di riprodurre questo in alcun modo, ma qui ci sono due cose che potrebbero aiutare.

  • Provare a utilizzare RobolectricGradleTestRunner invece di RobolectricTestRunner
  • Non dovrebbe essere necessario per mettere l'altra libreria in testCompile.Quindi penso che si può rimuovere in modo sicuro testCompile(name: 'commonLib-1.0 1', ext: 'aar')

Fatemi sapere nei commenti se avete aggiornamenti dopo aver provato il diverso corridore.

1

The project itself is a library apk project that uses and references another library APK project.

Per questo tipo di progetti esiste un problema già noto https://github.com/robolectric/robolectric/issues/1796 ma si può aggirare esso.

Il problema di base è il comportamento di android/gradle per i progetti di libreria che è diverso rispetto ai progetti di applicazione. Ignora semplicemente per generare classi R dalle dipendenze di aar.

Per risolvere il problema è possibile fornire la propria classe R che contiene già tutti i valori R delle dipendenze. Ecco un esempio per la dipendenza appcompat

afterEvaluate { project -> 
    android.libraryVariants.each { variant -> 
    // one line for each aar dependency 
    tasks.getByName("assemble${variant.name.capitalize()}").dependsOn copyAppcompat 
    } 
} 

// copy it for each aar dependency and adjust it to your needs 
task copyAppcompat(type: Copy) { 

    // replace the base package with yours (all after /r/debug/) which contains your R.class 
    from 'build/generated/source/r/debug/com/example/core'.replace("/", File.separator) 

    // replace the library packages with yours (all after /test/java/) with your aar dependency base package 
    into 'src/test/java/android/support/v7/appcompat'.replace("/", File.separator) 

    // also replace the package declaration or you will get compile errors 
    filter { line -> line.contains('package com.example.core;') ? 'package android.support.v7.appcompat;' : line } 
    include 'R.java' 
} 

un progetto di esempio con la configurazione può essere trovato alla https://github.com/nenick/AndroidStudioAndRobolectric/tree/library-with-aar

+0

Salve, ho già il seguente script che corregge i problemi di appCompact ma non risolve il problema sulla mia effettiva terza parte di terze parti libar sto usando – jonney

+0

La variante appCompat è solo un esempio su come risolvere questo problema. La stessa cosa deve essere fatta per la tua lib di terze parti. Copia il 'task copyAppcompat' e rinominalo. Aggiungi una nuova riga '.dependsOn copyAppcompat' per il tuo nuovo copyTask. Quindi Regola tutti i percorsi in modo che corrispondano alla tua lib, per i dettagli vedi i commenti. – nenick

+0

non sono più familiare con la tua sintassi. bisogno di avere una lettura di gradle come il tuo codice sopra non funziona abbastanza per me. dice che il cannone trova la proprietà vari – jonney