在单元测试中,如何在不对路径进行硬编码的情况下从(桌面)文件系统上的json文件读取数据?
我想从文件中读取测试输入(用于我的解析方法),而不是创建静态字符串。
该文件与我的单元测试代码位于同一位置,但是如果需要,我也可以将其放置在项目中的其他位置。我正在使用Android Studio。
test_documents.json
哪里?资产目录?
在单元测试中,如何在不对路径进行硬编码的情况下从(桌面)文件系统上的json文件读取数据?
我想从文件中读取测试输入(用于我的解析方法),而不是创建静态字符串。
该文件与我的单元测试代码位于同一位置,但是如果需要,我也可以将其放置在项目中的其他位置。我正在使用Android Studio。
test_documents.json
哪里?资产目录?
Answers:
根据android-gradle-plugin
版本:
1. 1.5版或更高版本:
只需将json文件放入src/test/resources/test.json
并引用为
classLoader.getResource("test.json").
无需修改gradle。
2. 1.5以下的版本:(或由于某种原因上述解决方案不起作用)
确保您至少使用了Android Gradle插件1.1版。按照链接正确设置Android Studio。
创建test
目录。将单元测试类放在java
目录中,并将您的资源文件放在res
目录中。Android Studio应该将它们标记为如下:
创建gradle
任务以将资源复制到classes目录中,以使其可见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());
}
src/test/resources/test.json
并将其引用为classLoader.getResource("test.json")
。无需修改gradle。内部的嵌套文件夹resources
也可以正常工作。
classLoader
啊 这行代码放在哪里?返回结果如何处理?请提供更完整的代码。-1
./src/test/resources/file.txt
在科特林阅读:TestClassName::class.java.getResource("/file.txt")!!.readText()
对于本地单元测试(与工具测试),您可以将文件放在下面src/test/resources
并使用classLoader读取它们。例如,以下代码myFile.txt
在资源目录中打开文件。
InputStream in = this.getClass().getClassLoader().getResourceAsStream("myFile.txt");
它与
val myFile = ClassLoader.getSystemResource("myFile.txt").readText()
就我而言,解决方案是将其添加到gradle文件中
sourceSets {
test.resources.srcDirs += 'src/unitTests/resources'
}
之后,一切由AS 2.3.1找到
javaClass.classLoader.getResourceAsStream("countries.txt")
root/app/src/test/resources/test.json
2.读取像这样的数据:val jsonFile = ClassLoader.getSystemResource("test.json").readText()
Android Studio中的测试资源存在很多问题,因此为了清晰起见,我设置了一些测试。在我的
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"));
在相同的根项目我有一个Java的(不是安卓)项目叫data
。如果我将相同文件添加到数据项目中:
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
。为了解决这个问题,我使用了这个技巧(在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
getClassLoader()
版本按预期工作。也就是说,他们找到了文件,它们都可以从Android Studio以及从我的macOS机器上的命令行以及Linux CI服务器(CircleCI)上运行。所以我要继续下去,希望Gradle 3.3以后不会破坏它……
build/resources/test
未包含在交互式类路径中,因此这些测试从命令行运行,但无法通过AS运行。
如果转到运行->编辑配置-> JUnit,然后为单元测试选择运行配置,则存在“工作目录”设置。那应该指向您的json文件在哪里。请记住,这可能会破坏其他测试。
new File()
或类似方式加载文件,但不适用于上述的类路径加载方法。这也有些棘手,因为每个新的运行配置都需要设置工作目录,并且默认情况下,AS和Gradle命令行喜欢使用不同的工作目录...这样的痛苦
我虽然应该在这里添加我的发现。我知道这有点旧,但是对于较新版本的Gradle,那里没有src / test / resources目录,但是整个项目只有一个资源目录,您必须将此行添加到Gradle文件中。
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
这样,您可以通过以下方式访问资源:
this.getClass().getClassLoader().getResourceAsStream(fileName);
我一直在搜索此内容,但找不到答案,因此我决定在这里帮助其他人。