简体   繁体   English

本地单元测试:读取生产资源时,getResourceAsStream

[英]Local Unit test: getResourceAsStream when reading production resource

There are a ton questions regarding getResource or getResourceAsStream returning null and so far I understand the issue but I currently cannot properly solve it. 关于getResource或getResourceAsStream返回null的问题很多,到目前为止,我理解了这个问题,但目前无法正确解决。

I have a resource file which is used by some class in production. 我有一个资源文件,供生产中的某些类使用。 The file is located in 该文件位于

app\\src\\main\\res\\raw\\some.def

The class SomeManager uses this to access this file: SomeManager类使用此文件来访问此文件:

InputStream stream = SomeClass.class.getResourceAsStream("/res/raw/some.def");

This succeeds when running the debug variant of the application on the emulator and it also succeeds when running the debug variant of the instrumented tests. 在模拟器上运行应用程序的调试版本时,此操作成功;在运行已测试的调试版本中时,此操作也成功。 I assume because the resource is properly packaged into the jar? 我认为是因为资源已正确包装到jar中了?

However when I run some local jUnit tests in android studio this resource is not found. 但是,当我在android studio中运行一些本地jUnit测试时,找不到此资源。 I did not fully understand what is exactly executed when running a local test and I am not sure how to provide the resource file in a way that can be loaded in a test. 我不完全了解运行本地测试时将执行什么操作,并且不确定如何以可以在测试中加载的方式提供资源文件。

I would like to avoid doubling this resource file because it is actually something I want to test, I also would like to not change the getResourceAsStream path because this is the production file I want to test. 我想避免将此资源文件加倍,因为它实际上是我要测试的东西,我也不想更改getResourceAsStream路径,因为这是我要测试的生产文件。

I am using gradle and android studio if that matters. 如果这很重要,我正在使用gradle和android studio。

I debugged this issue with Sysinternal's Process Monitor and realized that when I run code locally on my machine the resources are as streams are looked up from various different locations on disk. 我使用Sysinternal的Process Monitor调试了此问题,并意识到,当我在计算机上本地运行代码时,资源就如同从磁盘上各个不同位置查找流一样。 One of those locations is <build_directory>/intermediate/classes/<build_type> where it is obviously missing. 这些位置之一是<build_directory>/intermediate/classes/<build_type> ,该位置显然丢失了。

The solution to this was to create a copy task that performs the copying and make it robust enough to work for all build types. 解决方案是创建一个复制任务,该任务执行复制并使其足够健壮以适合所有构建类型。

So I modified my app's gradle file and added those dynamic tasks: 因此,我修改了应用程序的gradle文件并添加了这些动态任务:

android.buildTypes.all{ theBuildType ->
    task "copyDebugAssets_${theBuildType.name}"(type: Copy){

        from "${projectDir}/src/main/res"
        into "${buildDir}/intermediates/classes/${theBuildType.name}/res"
        eachFile { println it.name }
    }
}

tasks.whenTaskAdded { task ->

    // println "A message which is logged at QUIET level ${task.name}"
    if (task.name.startsWith("process") && task.name.endsWith("Resources")) {

        def partInBetween = task.name.substring("process".length(), task.name.indexOf("Resources")).toLowerCase()
        if (partInBetween == "debugandroidtest") {
            return
        }
        def dependentTask = "copyDebugAssets_${partInBetween}"
        println "Registering ${dependentTask} to ${task.name} for config '${partInBetween}'"
        task.dependsOn dependentTask
    }

}

I have really no idea on how to properly use gradle but the first statement generates as many copyDebugAssets_xxx tasks as there are build types. 我真的不知道如何正确使用gradle,但是第一条语句会生成与构建类型一样多的copyDebugAssets_xxx任务。 After syncing you can see and execute the in the gradle projects. 同步后,您可以在gradle项目中查看并执行。

To avoid calling them whenever a clean or rebuild is done manually, the second part registers the copyDebugAssets_xxx copy tasks to the various process<Configuration>Resources tasks, which are then called automatically. 为了避免每次手动执行清理或重建操作时调用它们,第二部分将copyDebugAssets_xxx复制任务注册到各种process<Configuration>Resources任务中,然后自动调用它们。 So far I can run local unit tests in multiple build type successfully. 到目前为止,我可以成功地以多种构建类型运行本地单元测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM