webentwicklung-frage-antwort-db.com.de

Wie kann ich während der Testausführung auf Dateien aus dem Assets-Ordner zugreifen?

Wie kann ich während der Ausführung von Komponententests auf Dateien aus dem Assets-Ordner zugreifen? Mein Projekt wird mit Gradle erstellt. Ich verwende Robolectric, um Tests durchzuführen. Es scheint, als würde gradle die assets erkennen:

enter image description here

So habe ich Mühe, 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. Den Pfad zu einer Datei mit verschiedenen Ansätzen definiert.

Vielen Dank im Voraus.

15
Eugene

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

Ich habe ein separates app-unit-test-Modul hinzugefügt, um Robolectric-Testfälle in einem App-Projekt auszuführen. Mit der richtigen Build-Konfiguration und dem benutzerdefinierten RobolectricTestRunner werden die folgenden Testfälle 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 benutzerdefinierten RobolectricTestRunner hinzu, um Dateipfade anzupassen. Sehen Sie sich den Pfad der Assets 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 bin diesem Blog gefolgt, um es zu tun.

Vollständige Beispielcodes sind hier .

10
Chk0nDanger

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

Ich lege Testdateien in den src/test/resources-Ordner anstelle des Assets-Ordners.

Dann bekomme ich diese Dateien auf folgende Weise als Stream

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

filename ist der relative Pfad zur Datei im resources-Ordner.

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

8
Andrii Panasiuk

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

Siehe auch 

  1. 2.4 auf 3.0 Upgrade Guide
  2. 3.0 auf 3.1 Upgrade Anleitung

de Guide

6
Nicks

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

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

Beim Robolectric müssen wir folgendes berücksichtigen:

Standardmäßig geht Robolectric davon aus, dass sich Ihre Ressourcen und Assets in Verzeichnissen mit den Namen res bzw. assets befinden. Es wird angenommen, dass diese Pfade relativ zu dem Verzeichnis sind, in dem sich das Manifest befindet. Sie können diese Werte ändern, indem Sie die Optionen resourceDir und assetDir der Annotation @Config hinzufügen.

Siehe die offiziellen docs

0
SHoko

Haben Sie versucht, den Assets-Ordner unter main statt androidTest zu platzieren?

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

0
kageiit