对于我的Android应用,我正在编写需要阅读一些文件的单元测试。由于这些是纯测试文件,因此我不希望它们出现在我的res
文件夹中,因为我不希望它们最终出现在我的.apk
文件中。
我想做类似this question的事情,但是使用新添加的(在Gradle 1.1中)unit test support(而不是仪器测试)。
我的项目结构如下:
/app
/src
/main
/java/my.module/myClass.java
/res/production_resources_go_here
/test
/java/my.module/myClassTest.java
/resources/testFile.txt
我的myClassTest
测试应该如何才能成功阅读testFile.txt
?
答案 0 :(得分:34)
在提出这个问题时,这根本不起作用。幸运的是,这已经得到修复。
您必须将文本文件放在{I}尝试执行的app/src/test/resources
文件夹下。此外,它必须与您的测试类位于同一个包中。因此,如果ReadFileTest.java
文件夹中的com.example.test
包中有app/src/test/java
,则您的测试文件应位于app/src/test/resources/com/example/test
。
然后你可以这样找到你的文本文件:
getClass().getResourceAsStream("testFile.txt")
这会为文本文件打开InputStream
。如果您不确定如何使用它,可以使用以下几种方法:Read/convert an InputStream to a String
答案 1 :(得分:6)
将此添加到build.gradle:
android {
sourceSets {
test {
resources.srcDirs += ['src/test/resources']
}
androidTest {
resources.srcDirs += ['src/androidTest/resources']
}
}
}
要获得单元测试可访问的资源,请将文件添加到:src/test/resources
。
对于仪器测试,请将您的文件添加到:src/androidTest/resources
。
答案 2 :(得分:2)
在@ Deepansu的回答之后,我统一了{project root}/sampledata
目录中的测试数据,这是Android Studio New > Sample Data Directory
命令的默认位置。
1。在您的项目中,右键单击并单击New > Sample Data Directory
。这将在sampledata
中创建app
目录,该目录与build.gradle
文件,src
和build
目录具有相同的层次结构。
2。在build.gradle
中,添加如下脚本;
android {
sourceSets {
test {
resources.srcDirs += ['sampledata']
}
androidTest {
resources.srcDirs += ['sampledata']
}
}
}
在gradle中 3。 Sync
。
现在,我们可以将测试资源文件放在一个目录中,并在两个测试环境中使用它们。
您可以阅读以下文件;
// use somewhere at test logic. Note that slash symbol is required (or not).
jsonObject = new JSONObject(readFromFile("/testFile.json"));
// a method to read text file.
public String readFromFile(String filename) throws IOException {
InputStream is = getClass().getResourceAsStream(filename);
StringBuilder stringBuilder = new StringBuilder();
int i;
byte[] b = new byte[4096];
while ((i = is.read(b)) != -1) {
stringBuilder.append(new String(b, 0, i));
}
return stringBuilder.toString();
}
答案 3 :(得分:1)
我正在开展一个类似于你提到的结构的项目。
我将所有服务器响应放在resources
app/src/test/resources/BookingInfo.json
文件夹下的文件中。
所有java测试文件都在app/src/test/java/PACKAGE_NAME
下,与您所说的相似。我在包含资源名称的包下有一个Fixture
类:
@SuppressWarnings("nls")
public final class Fixtures
{
public static final String GET_ANNOUNCEMENT = "GetAnnouncement.json";
...
}
最后一个FixtureUtils类,该类的方法负责读取资源文件并返回结果。
import java.nio.file.Files;
import java.nio.file.Paths;
public class FixtureUtils
{
public static final AFixture fixtureFromName(final String fixtureName)
{
final String fixtureString = FixtureUtils.stringFromAsset(fixtureName);
if (StringUtils.isEmpty(fixtureString))
{
return null;
}
final Gson gson = new Gson();
final AFixture aFixture = gson.fromJson(fixtureString, AFixture.class);
return aFixture;
}
private static final String stringFromAsset(final String filename)
{
try
{
final URL resourceURL = ClassLoader.getSystemResource(filename);
if (resourceURL == null)
{
return null;
}
final String result = new String(Files.readAllBytes(Paths.get(resourceURL.toURI())),
Charset.forName("UTF-8")); //$NON-NLS-1$
return result;
}
catch (final Exception e)
{
e.printStackTrace();
}
return null;
}
private FixtureUtils()
{
// Ensure Singleton
}
}
并且AFixture
类看起来像:
public class AFixture
{
public List<JsonElement> validItems;
public List<JsonElement> invalidItems;
public AFixture()
{
super();
}
public List<JsonElement> getInvalidItems()
{
return this.invalidItems;
}
public List<JsonElement> getValidItems()
{
return this.validItems;
}
public void setInvalidItems(final List<JsonElement> invalidItems)
{
this.invalidItems = invalidItems;
}
public void setValidItems(final List<JsonElement> validItems)
{
this.validItems = validItems;
}
}
注意:java.nio.file
已从JDK8中移除,如果我没有弄错,但如果您使用的是JDK7则没有问题。如果您使用的是JDK8,那么您只需要以FileInputStream(旧时尚风格)或Scanner等方式更改stringFromAsset
方法。
答案 4 :(得分:0)
以下是一种更好且更通用的方法。它也适用于其他项目类型,例如Spring。另一个好处是您不必将文件专门放在包结构中的某个位置。这种依赖关系不应该(依赖于包的结构)。如果文件名正确(具有测试文件夹结构),则使它更具可读性。
this.getClass().getClassLoader().getResourceAsStream(filename);
一个例子:
private String htmlFromTestResourceFile(String filename) {
try {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filename);
return IOUtils.toString(inputStream, "UTF-8");
} catch( Exception e) {
e.printStackTrace();
return null;
}
}
答案 5 :(得分:-2)
执行此操作的正确方法的示例是将文件放在assets文件夹中。但是,assets文件夹的内容将添加到apk中。
InputStream is = resources.getAssets().open("test.txt");
您可以欺骗此系统并遍历项目中的任何其他文件。确保在项目的iml文件中指定的位置创建资产目录(例如src / main / assets)。
InputStream is = resources.getAssets().open("../../test/resources/testFile.txt");
获取资源的一种方法是:
Resources resources = new Activity().getResources();