Android Studio 单元测试: 读取数据(输入)文件

在单元测试中,如何在不对路径进行硬编码的情况下从我的(桌面)文件系统上的 json 文件读取数据?

我希望从文件中读取测试输入(用于我的解析方法) ,而不是创建静态 String。

The file is in the same location as my unit testing code, but I can also place it somewhere else in the project if needed. I am using Android Studio.

68736 次浏览

视乎 android-gradle-plugin版本:

1.5或以上版本:

只需将 json 文件放入 src/test/resources/test.json并将其引用为

classLoader.getResource("test.json").

不需要修改等级。

2.1.5以下版本 : (或者由于上述解决方案不起作用)

  1. 请确保您至少使用了 Android Gradle 插件版本1.1。请按照链接正确设置 Android Studio。

  2. 创建 test目录。将单元测试类放在 java目录中,并将资源文件放在 res目录中。Android Studio 应该标记如下:

    enter image description here

  3. 创建 gradle任务,将资源复制到 class 目录中,使它们对于 classloader可见:

    android{
    ...
    }
    
    
    task copyResDirectoryToClasses(type: Copy){
    from "${projectDir}/src/test/res"
    into "${buildDir}/intermediates/classes/test/debug/res"
    }
    
    
    assembleDebug.dependsOn(copyResDirectoryToClasses)
    
  4. Now you can use this method to get File reference for the file resource:

    private static File getFileFromPath(Object obj, String fileName) {
    ClassLoader classLoader = obj.getClass().getClassLoader();
    URL resource = classLoader.getResource(fileName);
    return new File(resource.getPath());
    }
    
    
    @Test
    public void fileObjectShouldNotBeNull() throws Exception {
    File file = getFileFromPath(this, "res/test.json");
    assertThat(file, notNullValue());
    }
    
  5. Run unit test by Ctrl+Shift+F10 on whole class or specyfic test method.

If you go to Run -> Edit configurations -> JUnit and then select the run configuration for your unit tests, there is a 'Working directory' setting. That should point to wherever your json file is. Keep in mind this might break other tests.

For local unit tests (vs. instrumentation tests), you can put files under src/test/resources and read them using classLoader. For example, following code opens myFile.txt file in the resources directory.

InputStream in = this.getClass().getClassLoader().getResourceAsStream("myFile.txt");

这招很管用

  • Android Studio 1.5.1
  • Gradle 插件1.3.1

I've had plenty of problems with test resources in Android Studio so I set up a few tests for clarity. In my mobile(Android 应用程序)项目我添加了以下文件:

mobile/src/test/java/test/ResourceTest.java
mobile/src/test/resources/test.txt
mobile/src/test/resources/test/samePackage.txt

测试类(所有测试都通过) :

assertTrue(getClass().getResource("test.txt") == null);
assertTrue(getClass().getResource("/test.txt").getPath().endsWith("test.txt"));
assertTrue(getClass().getResource("samePackage.txt").getPath().endsWith("test/samePackage.txt"));
assertTrue(getClass().getResource("/test/samePackage.txt").getPath().endsWith("test/samePackage.txt"));
assertTrue(getClass().getClassLoader().getResource("test.txt").getPath().endsWith("test.txt"));
assertTrue(getClass().getClassLoader().getResource("test/samePackage.txt").getPath().endsWith("test/samePackage.txt"));

在同一个根项目中,我有一个名为 dataJava (非 Android)项目。如果向数据项目添加相同的文件:

data/src/test/java/test/ResourceTest.java
data/src/test/resources/test.txt
data/src/test/resources/test/samePackage.txt

Then all the tests above will fail if I execute them from Android Studio, but they pass on the command line with ./gradlew data:test. 为了解决这个问题,我使用了这个代码(在 Groovy 中)

def resource(String path) {
getClass().getResource(path) ?:
// Hack to load test resources when executing tests from Android Studio
new File(getClass().getClassLoader().getResource('.').path
.replace('/build/classes/test/', "/build/resources/test$path"))
}

用法: resource('/test.txt')

Android Studio 2.3,Gradle 3.3

在我的例子中,解决方案是添加到 gradle 文件

sourceSets {
test.resources.srcDirs += 'src/unitTests/resources'
}

之后,所有的东西都被 AS2.3.1找到了

javaClass.classLoader.getResourceAsStream("countries.txt")

I though I should add my findings here. I know this is a little old but for the newer versions of Gradle, where there is NO src/test/resources directory, but only one single resources directory for the whole project, you have to add this line to your Gradle file.

android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}

By doing this you can access your resource with:

 this.getClass().getClassLoader().getResourceAsStream(fileName);

我一直在寻找这个答案,但是找不到,所以我决定帮助这里的其他人。

实际上,这就是我在仪器测试(运行 Android Studio 版本 3.5.3,Android Gradle 插件版本 3.5.3,Gradle 版本 6.0.1)中的工作原理:

  1. 把你的文件放在 src/androidTest/assets文件夹
  2. 在您的测试文件中:

InputStream is = InstrumentationRegistry.getInstrumentation().getContext().getAssets().open("filename.txt");

步骤(1)打开 Android Studio 选择项目视图

步骤(2)并创建测试下的资源目录。

Please look at attached screenshot for Step(2) result

enter image description here

步骤(3)将 json 文件放入 resources 文件夹(app/src/test/resources)

请看附件中第(3)步结果的截图

enter image description here

Step(4) Create a common class to handle reading local json files and converting to respective models using Gson

例子:-

object TestHelper {
private val gson = Gson()


fun loadJsonAsString(fileName: String): String {
val inputStream = javaClass.getResourceAsStream("/$fileName")
return getStringFromInputStream(inputStream)
}


@Throws(IOException::class)
private fun getStringFromInputStream(stream: InputStream?): String {
var n = 0
val buffer = CharArray(1024 * 4)
val reader = InputStreamReader(stream, "UTF8")
val writer = StringWriter()
while (-1 != reader.read(buffer).also { n = it }) writer.write(buffer, 0, n)
return writer.toString()
}


fun <T> convertJsonToModel(jsonString: String, classT: Class<T>): T{
return gson.fromJson(jsonString, classT)
}
}

步骤(5)加载本地存储在 步骤(2)中创建的 resources 目录中的 json 文件

val GET_USER_INFORMATION_RESPONSE_FILE_NAME = "user_response.json"
val jsonString = loadJsonAsString(GET_USER_INFORMATION_RESPONSE_FILE_NAME)
val networkStatusResponse =
convertJsonToModel(jsonString, UserResponse::class.java)

步骤(6)在 步骤(5)的末尾,您已经将本地 json 文件转换为所需的模型类,这些模型类可以用来编写您的单元测试。

在我的情况下,我只需要创建 resources文件夹到 test文件夹,并把我的资源文件在该文件夹。 然后,在测试中简单地将文件作为资源流加载:

val inputStream =
this.javaClass.classLoader?.getResourceAsStream("gallery.xml")

enter image description here

Reference on medium: https://medium.com/mobile-app-development-publication/android-reading-a-text-file-during-test-2815671e8b3b