web-dev-qa-db-fra.com

Comment accéder aux fichiers du dossier assets lors de l'exécution des tests?

Comment accéder aux fichiers du dossier assets pendant l'exécution des tests unitaires? Mon projet est construit avec Gradle, j'utilise Robolectric pour exécuter des tests. Il semble que Gradle reconnaisse la assets:

enter image description here

Voici comment j'ai du mal à lire le fichier:

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

Mais stream est toujours null. Je l’ai essayé de différentes manières, c’est-à-dire le chemin défini vers un fichier en utilisant différentes approches.

Merci beaucoup d'avance.

15
Eugene

Fondamentalement, vous devez utiliser Context pour lire les actifs. Vous ne pouvez pas charger d'actifs avec ClassLoader car ce n'est pas dans un chemin de classe. Je ne suis pas sûr de savoir comment vous exécutez les cas de test Robolectric. Voici comment je peux réaliser à la fois dans Android studio et dans la commande gralde.

J'ai ajouté un module de test d'unité d'application distinct pour exécuter les scénarios de test Robolectric dans un projet d'application. Avec une configuration de construction appropriée et une variable RobolectricTestRunner personnalisée, le scénario de test suivant est accepté.

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

Ajoutez RobolectricTestRunner personnalisé pour ajuster les chemins de fichiers. Consultez le chemin des ressources.

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

}

J'ai suivi ce blog pour le faire.

Des exemples de codes complets sont ici .

10
Chk0nDanger

Je viens de me retrouver avec le même problème et voici comment cela fonctionne pour moi.

Je mets les fichiers de test dans le dossier src/test/resources au lieu du dossier assets.

Ensuite, je reçois ces fichiers comme flux de la manière suivante

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

filename est le chemin relatif du fichier dans le dossier resources.

C'est tout. J'ai trouvé la solution chez Robolectric github

8
Andrii Panasiuk

Mise à jour comme pour 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);
        }

Voir également 

  1. Guide de mise à niveau 2.4 à 3.0
  2. Guide de mise à jour 3.0 à 3.1

de Guide

6
Nicks

Avec le dernier test d'instrumentation Android, vous pouvez simplement utiliser ceci:

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

Lorsque Robolectric, nous devons tenir compte de ce qui suit:

Par défaut, Robolectric supposera que vos ressources et vos actifs se trouvent dans des répertoires nommés respectivement res et assets. Ces chemins sont supposés être relatifs au répertoire où se trouve le manifeste. Vous pouvez modifier ces valeurs en ajoutant les options resourceDir et assetDir à l'annotation @Config.

Voir le fonctionnaire docs

0
SHoko

Avez-vous essayé de placer le dossier des actifs sous main au lieu de androidTest?

En outre, utilisez-vous https://github.com/robolectric/robolectric-gradle-plugin pour exécuter vos tests?

0
kageiit