2014-11-07 7 views
12

Zugriff auf Dateien im Ordner "Assets" während der Ausführung der Komponententests? Mein Projekt wird mit Gradle erstellt. Ich verwende Robolectric, um Tests auszuführen. Es scheint, wie gradle wird die assets erkennen:Zugriff auf Dateien aus Assets-Ordner während der Testausführung?

enter image description here

Dies ist, wie ich kämpfen, um die Datei zu lesen:

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); 
} 

Aber stream ist immer null. Ich habe es auf viele verschiedene Arten versucht, d. H. Einen Pfad zu einer Datei unter Verwendung verschiedener Ansätze definiert.

Vielen Dank im Voraus.

+0

Gilt dies? http://stackoverflow.com/questions/20184480/loading-assets-in-andandroid-test-project –

+0

Nein, es ist nicht InstrumentationTestCase – Eugene

+0

Nun, vielleicht muss es sein. –

Antwort

10

Grundsätzlich müssen Sie Context verwenden, um Assets zu lesen. Sie können Assets nicht mit ClassLoader laden, da es sich nicht in einem Klassenpfad befindet. Ich bin mir nicht sicher, wie Sie Robolectric-Testfälle ausführen. Hier ist, wie ich in Android Studio und gralde Befehl erreichen kann.

Ich habe ein separates App-Unit-Testmodul hinzugefügt, um Robolectric-Testfälle in einem App-Projekt auszuführen. Mit der richtigen Buildkonfiguration und benutzerdefiniertem RobolectricTestRunner wird der folgende Testfall bestanden.

@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') 
} 

Fügen Sie benutzerdefinierte RobolectricTestRunner Dateipfade zu ändern. Sehen Sie sich den Anlagenpfad an.

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); 
    } 

} 

Ich folgte diesem Blog, um es zu tun.

Voll Beispiel-Codes sind here.

-2

Wenn alles korrekt ist, dann werden Sie so etwas wie dieses benötigen, es zu lesen:

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); 
} 

Sie müssen Kontext passieren, damit es funktioniert.

Eine andere Sache, um zu überprüfen, ob Sie Assets in Gradle korrekt konfiguriert haben? Hier ist nur ein Beispiel:

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

Haben Sie versucht, die Assets Ordner unter Haupt anstelle von AndroidTest?

Verwenden Sie auch https://github.com/robolectric/robolectric-gradle-plugin, um Ihre Tests auszuführen?

+0

auf diese Weise würden sie in Anwendung kompilieren, die ich vermeiden muss. – Eugene

+0

Nein, ich verwende https://github.com/robolectric/deckard-gradle, um meine Tests auszuführen. – Eugene

5

Aktualisierung wie bei Roboelektrik 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); 
     } 

Siehe auch

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

de Führer

+1

Funktioniert nicht für mich, 'RuntimeEnvironment.application.getAssets(). Open' gibt eine' IOException' zurück, und ich füge Assets-Ordner hinzu: https://gist.github.com/nebiros/4d6370c3ba87f3dd6f6a. – nebiros

+0

Funktioniert für mich. Dies öffnet jedoch Dateien im Ordner "Assets" des Hauptquellsets und nicht beim Test (was ich suche). –

5

Ich habe gerade mit dem gleichen Problem stecken und hier ist, wie es funktioniert für mich.

Ich legte Testdateien auf src/test/resources Ordner statt Asset-Ordner.

Dann bekomme ich diese Dateien als Stream im Weg folgenden

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

filename der relative Pfad innerhalb resources Ordner auf die Datei ist.

Das ist es. Ich habe Lösung gefunden bei Robolectric github

3

Mit dem neuesten Android Instrumentation Test können Sie nur verwenden:

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