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

Posted

技术标签:

【中文标题】Android Studio 单元测试:读取数据(输入)文件【英文标题】:Android Studio unit testing: read data (input) file 【发布时间】:2015-06-03 04:55:02 【问题描述】:

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

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

该文件与我的单元测试代码位于同一位置,但如果需要,我也可以将其放置在项目中的其他位置。我正在使用 android Studio。

【问题讨论】:

我尝试了几乎所有与 IOUtils.toString(this.getClass().getResourceAsStream("test_documents.json"), "UTF-8") 的组合,它总是返回 null。可能是因为文件不会包含在 jar 中。 我们是在谈论涉及安卓模拟器/设备的单元测试吗? @Android777 我想我们正在谈论最新版本的 Android Studio 中引入的新单元测试支持tools.android.com/tech-docs/unit-testing-support @Frank 你把test_documents.json放在哪里?资产目录? 是的,我们谈论的是新的单元测试支持,不涉及模拟器/设备。我没有将它放在资产目录中,因为它会与实时 apk 打包在一起。我把它和测试(java)文件放在同一个文件夹中。 【参考方案1】:

取决于android-gradle-plugin 版本:

1. 1.5 及更高版本:

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

classLoader.getResource("test.json"). 

无需修改gradle。

2。低于 1.5 的版本:(或者如果由于某种原因上述解决方案不起作用)

    确保您至少使用Android Gradle Plugin version 1.1。按照链接正确设置 Android Studio。

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

    创建gradle 任务以将资源复制到类目录中,以使它们对classloader 可见:

    android
       ...
    
    
    task copyResDirectoryToClasses(type: Copy)
        from "$projectDir/src/test/res"
        into "$buildDir/intermediates/classes/test/debug/res"
    
    
    assembleDebug.dependsOn(copyResDirectoryToClasses)
    

    现在您可以使用此方法获取文件资源的File 引用:

    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());
    
    
    通过 Ctrl+Shift+F10 对整个类或特定测试方法运行单元测试。

【讨论】:

太棒了!你的编辑,没有工具测试,就像一个魅力,谢谢! 这是一个很好的解决方案,但它并不总是有效。如果您执行运行 clean 任务,然后运行 ​​testDebug 它会失败。基本上,开发人员需要知道他必须在 testDebug 之前运行 assembleDebug 任务。大家有什么改进的建议吗? 使用带有 android 插件 1.5.0 的 AndroidStudio 1.5 将您的 json 文件放在此处 src/test/resources/test.json 并将其引用为 classLoader.getResource("test.json")。不需要 gradle 修改。 resources 内的嵌套文件夹也可以使用。 答案不完整。 classLoader 是什么?在哪里放置这行代码?你能用返回结果做什么?请提供更完整的代码。 -1 在 Kotlin 中阅读 ./src/test/resources/file.txtTestClassName::class.java.getResource("/file.txt")!!.readText()【参考方案2】:

对于本地单元测试(与仪器测试相比),您可以将文件放在src/test/resources 下并使用类加载器读取它们。例如,以下代码在资源目录中打开myFile.txt 文件。

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

它适用于

Android Studio 1.5.1 gradle 插件 1.3.1

【讨论】:

这对我不起作用,请在此处查看我的问题***.com/questions/36295824/… 当我从“src/test/res”更改为“src/test/resources”时,这对我有用。使用 Android Studio 2.0 RC 3,gradle:2.0.0-rc3 按预期工作。但是即使文件在“src/test/resources/”下不可用,测试也会通过,例如:“rules.xml”,但在这种情况下 InputStream 结果为 null。 科特林:val myFile = ClassLoader.getSystemResource("myFile.txt").readText() 工作就像魅力!【参考方案3】:

就我而言,解决方案是添加到 gradle 文件中

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

之后,AS 2.3.1 找到了一切

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

【讨论】:

我做了一些非常相似的事情(Kotlin):1. 创建文件夹和文件:root/app/src/test/resources/test.json 2. 读取这样的数据:val jsonFile = ClassLoader.getSystemResource("test.json").readText()【参考方案4】:

虽然我应该在这里添加我的发现。我知道这有点旧,但是对于较新版本的 Gradle,没有 src/test/resources 目录,但整个项目只有一个资源目录,您必须将此行添加到您的 Gradle 文件中。

android 
   testOptions 
      unitTests 
         includeAndroidResources = true
      
    

通过这样做,您可以通过以下方式访问您的资源:

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

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

【讨论】:

谢谢拉斐尔·艾尔斯。这应该是票数最高的评论。此外,您需要在 src/test/ 下创建资源目录,因此您最终将拥有 src/test/resources/...【参考方案5】:

我在 Android Studio 中的测试资源方面遇到了很多问题,因此为了清楚起见,我设置了一些测试。在我的 mobile (Android Application) 项目我添加了以下文件:

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

然后,如果我从 Android Studio 执行上述所有测试,它们都会失败,但它们会在命令行中以 ./gradlew data:test 传递。 为了解决这个问题,我使用了这个 hack(在 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

【讨论】:

很好的答案(经过 45 分钟的搜索 ?)。它触及了几个问题的核心,并使得使用测试本身复制结果变得容易。 Fwiw,在 AS 2.3.1、Gradle 2.3.1 中,getClassLoader() 版本按预期工作。 IE。他们找到了这些文件,它们都是从 Android Studio 和我的 macOS 机器上的命令行以及 Linux CI 服务器 (CircleCI) 上运行的。所以我会继续这样做,并希望 Gradle 3.3 以后不会破坏它...... 不错!我在这里看到了相同的资源加载问题。作为 2.3.2,Gradle 3.3。由于build/resources/test 未包含在交互式类路径中,因此测试从命令行工作,但不能通过 AS。【参考方案6】:

如果您转到运行 -> 编辑配置 -> JUnit,然后为您的单元测试选择运行配置,则有一个“工作目录”设置。那应该指向您的 json 文件所在的位置。请记住,这可能会破坏其他测试。

【讨论】:

而不是使用 this.getClass().getResourceAsStream(test.json) ?我在那里添加了文件,在项目的根目录中,它仍然找不到文件。 这可用于使用new File() 或类似方法加载文件,但不能直接与上述类路径加载方法一起使用。这也有点棘手,因为每个新的运行配置都需要设置工作目录,并且默认情况下 AS 和 Gradle 命令行喜欢使用不同的工作目录......这样的痛苦【参考方案7】:

实际上,这对我来说是有效的 Instrumentation 测试(运行 Android Studio 版本 3.5.3、Android Gradle 插件版本 3.5.3、Gradle 版本 6.0.1):

    将文件放入src/androidTest/assets文件夹 在您的测试文件中:

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

【讨论】:

这适用于仪器测试。这在单元测试中对您有用吗(无仪器测试)? @displayname 观看this question。我想知道同样的事情。

以上是关于Android Studio 单元测试:读取数据(输入)文件的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio系列-单元测试入门篇

Visual Studio 2017 中的 Xamarin (Android) 单元测试

Android Studio 单元测试配置

Android Studio系列-Activity单元测试

Android Studio中的Android Instrumentation测试和单元测试之间的区别?

如何使用 Android Studio 运行单元测试