2014-11-07 15 views
12

Come accedere ai file dalla cartella delle risorse durante l'esecuzione dei test unitari? Il mio progetto è costruito usando Gradle, io uso Robolectric per eseguire i test. Sembra che Gradle sta riconoscendo il assets:Come accedere ai file dalla cartella delle risorse durante l'esecuzione dei test?

enter image description here

Ecco come sto lottando per leggere il file:

public String readFileFromAssets(String fileName) throws IOException { 
    InputStream stream = getClass().getClassLoader().getResourceAsStream("assets/" + fileName); 
    Preconditions.checkNotNull(stream, "Stream is null"); 
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8")); 
    return IOUtils.toString(reader); 
} 

Ma stream è sempre null. L'ho provato in molti modi diversi, ad esempio il percorso definito di un file utilizzando approcci diversi.

Grazie mille in anticipo.

+0

si applica questo? http://stackoverflow.com/questions/20184480/loading-assets-in-an-android-test-project –

+0

No, non è InstrumentationTestCase – Eugene

+0

Beh, forse deve essere. –

risposta

10

Fondamentalmente è necessario utilizzare Context per leggere le risorse. Non è possibile caricare le risorse con ClassLoader poiché non si trova in un classpath. Non sono sicuro di come gestisci i casi di test Robolectric. Ecco come posso ottenere in entrambi i comandi Android Studio e Gralde.

Ho aggiunto un modulo di app-unit-test separato per eseguire i casi di test Robolectric nel progetto di app. Con la corretta configurazione di build e personalizzata RobolectricTestRunner, il caso di test seguente verrà superato.

@Config 
@RunWith(MyRobolectricTestRunner.class) 
public class ReadAssetsTest { 

    @Test 
    public void test_ToReadAssetsFileInAndroidTestContext() throws IOException { 

     ShadowApplication application = Robolectric.getShadowApplication(); 
     Assert.assertNotNull(application); 
     InputStream input = application.getAssets().open("b.xml"); 
     Assert.assertNotNull(input); 
    } 

} 

app-unit-test/build.gradle

buildscript { 
    repositories { 
     jcenter() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:0.14.1' 
    } 
} 

apply plugin: 'java' 
evaluationDependsOn(':app') 

sourceCompatibility = JavaVersion.VERSION_1_7 
targetCompatibility = JavaVersion.VERSION_1_7 

repositories { 
    maven { url "$System.env.ANDROID_HOME/extras/android/m2repository" } // Fix 'com.android.support:*' package not found issue 
    mavenLocal() 
    mavenCentral() 
    jcenter() 
} 

dependencies { 
    testCompile 'junit:junit:4.8.2' 
    testCompile('org.robolectric:robolectric:2.4') { 
     exclude module: 'classworlds' 
     exclude module: 'commons-logging' 
     exclude module: 'httpclient' 
     exclude module: 'maven-artifact' 
     exclude module: 'maven-artifact-manager' 
     exclude module: 'maven-error-diagnostics' 
     exclude module: 'maven-model' 
     exclude module: 'maven-project' 
     exclude module: 'maven-settings' 
     exclude module: 'plexus-container-default' 
     exclude module: 'plexus-interpolation' 
     exclude module: 'plexus-utils' 
     exclude module: 'wagon-file' 
     exclude module: 'wagon-http-lightweight' 
     exclude module: 'wagon-provider-api' 
     exclude group: 'com.android.support', module: 'support-v4' 
    } 
    testCompile('com.squareup:fest-android:1.0.+') { 
     exclude group: 'com.android.support', module: 'support-v4' 
    } 
    testCompile 'org.mockito:mockito-core:1.10.10' 
    def appModule = project(':app') 
    testCompile(appModule) { 
     exclude group: 'com.google.android' 
     exclude module: 'dexmaker-mockito' 
    } 
    testCompile appModule.android.applicationVariants.toList().first().javaCompile.classpath 
    testCompile appModule.android.applicationVariants.toList().first().javaCompile.outputs.files 
    testCompile 'com.google.android:android:4.1.1.4' 
    /* FIXME : prevent Stub! error 
     testCompile files(appModule.plugins.findPlugin("com.android.application").getBootClasspath()) 
     */ 
    compile project(':app') 
} 

Aggiungi RobolectricTestRunner personalizzato per regolare i percorsi dei file. Guarda il percorso delle risorse.

public class MyRobolectricTestRunner extends RobolectricTestRunner { 

    private static final String APP_MODULE_NAME = "app"; 

    /** 
    * Creates a runner to run {@code testClass}. Looks in your working directory for your AndroidManifest.xml file 
    * and res directory by default. Use the {@link org.robolectric.annotation.Config} annotation to configure. 
    * 
    * @param testClass the test class to be run 
    * @throws org.junit.runners.model.InitializationError if junit says so 
    */ 
    public MyRobolectricTestRunner(Class<?> testClass) throws InitializationError { 
     super(testClass); 
     System.out.println("testclass="+testClass); 
    } 

    @Override 
    protected AndroidManifest getAppManifest(Config config) { 

     String userDir = System.getProperty("user.dir", "./"); 
     File current = new File(userDir); 
     String prefix; 
     if (new File(current, APP_MODULE_NAME).exists()) { 
      System.out.println("Probably running on AndroidStudio"); 
      prefix = "./" + APP_MODULE_NAME; 
     } 
     else if (new File(current.getParentFile(), APP_MODULE_NAME).exists()) { 
      System.out.println("Probably running on Console"); 
      prefix = "../" + APP_MODULE_NAME; 
     } 
     else { 
      throw new IllegalStateException("Could not find app module, app module should be \"app\" directory in the project."); 
     } 
     System.setProperty("android.manifest", prefix + "/src/main/AndroidManifest.xml"); 
     System.setProperty("android.resources", prefix + "/src/main/res"); 
     System.setProperty("android.assets", prefix + "/src/androidTest/assets"); 

     return super.getAppManifest(config); 
    } 

} 

Ho seguito questo blog per farlo.

codici di esempio completi sono here.

-2

Se tutto è corretto, allora avrete bisogno di qualcosa di simile per leggerla:

public String readFileFromAssets(String fileName, Context context) throws IOException { 
    InputStreamReader stream = new InputStreamReader(context.getAssets().open(fileName)); 
    Preconditions.checkNotNull(stream, "Stream is null"); 
    BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8")); 
    return IOUtils.toString(reader); 
} 

è necessario passare al contesto per farlo funzionare.

Un'altra cosa da verificare se sono state configurate correttamente le risorse in Gradle? Ecco un esempio:

sourceSets { 
    main { 
     java.srcDirs = ['src/main'] 
     // can be configured in different way 
     assets.srcDirs = ['src/androidTest/assets'] 
     // other things, examples 
     res.srcDirs = ['res'] 
     manifest.srcFile 'AndroidManifest.xml' 
    } 
} 
0

Hai provato a mettere la cartella delle risorse in main invece di androidTest?

Inoltre, stai usando https://github.com/robolectric/robolectric-gradle-plugin per eseguire i test?

+0

in questo modo si compilano in un'applicazione che ho bisogno di evitare. – Eugene

+0

No, sto usando https://github.com/robolectric/deckard-gradle per eseguire i miei test. – Eugene

5

Aggiornamento come per Roboelectric 3.1

@Test 
    public void shouldGetJSONFromAsset() throws Exception{ 
     Assert.assertNotNull(RuntimeEnvironment.application); //Getting the application context 
     InputStream input = RuntimeEnvironment.application.getAssets().open("fileName.xml");// the file name in asset folder 
     Assert.assertNotNull(input); 
     } 

Vedi anche

  1. 2.4 to 3.0 Upgrade Guide
  2. 3.0 to 3.1 Upgrade Guide

de Guida

+1

Non funziona per me, 'RuntimeEnvironment.application.getAssets(). Open' restituisce una' IOException' e aggiungo la cartella delle risorse come: https://gist.github.com/nebiros/4d6370c3ba87f3dd6f6a. – nebiros

+0

Funziona per me. Tuttavia, questo apre i file nella cartella delle risorse del gruppo di risorse principale e non in quella di test (che è ciò che sto cercando). –

5

Ho appena rimasto bloccato con lo stesso problema ed ecco come funziona per me.

Ho inserito i file di test nella cartella src/test/resources anziché nella cartella delle risorse.

tanto sono questi file come flusso in modo seguente

private InputStream openFile(String filename) throws IOException { 
     return getClass().getClassLoader().getResourceAsStream(filename); 
} 

filename è il percorso relativo al file all'interno della cartella resources.

Questo è tutto. Ho trovato la soluzione al Robolectric github

3

Con l'ultima Android strumentazione di prova, si può semplicemente utilizzare questo:

InstrumentationRegistry.getContext().getAssets().open(filePath);