I'm writing an Android JUnit test and want to copy/reset a test fixture file (it's an SQLite database file.) If I were within the main application, I know I could just place the file in the assets directory and use getResources().getAssets().open(sourceFile)
However, this API appears to be unavailable from the ActivityInstrumentationTestCase2
class.
Is there an easy way to copy a file over from the testing PC, or should I just keep a fresh copy of a test fixture on the device and copy it over a temporary file?
Thanks!
Unit tests shouldn't depend on infrastructure 🔗There's no way to test this function without a database connection available at the time of testing. If a new developer clones the project they will need to set up a database before they can successfully run the unit tests.
While unit testing a database might not be as common or familiar as unit testing application code, it's perfectly achievable!
Note: Instrumented test, also known as instrumentation tests, are initialized in a special environment that gives them access to an instance of Instrumentation. This class provides access to the application context and APIs to manipulate the app under test and gives instrumented tests their name.
The resources in your test application and your main application are accessible separately in an instrumentation test case. If you want to access resources that are in the res/raw or assets folder of the test project itself, you can use
getInstrumentation().getContext().getResources()
To access resources in the application being tested (the "target" application), use
getInstrumentation().getTargetContext().getResources()
Note, however, that you can never modify files in the assets folder;
getResources().getAssets().open(sourceFile)
returns an InputStream. There's no way to modify the file. That's because assets are stored compressed inside the APK, and are not really writeable at all.
If what you want to do is modify the path to the files the Activity you're testing uses, you should use ActivityUnitTestCase and setActivityContext() with a RenamingDelegatingContext. This allows you to redirect file and database access in a context to a new directory by specifying a directory prefix. You can even use the more complex constructor to wrap the target context for most operations, but use your test application's context for file operations, so the activity will access files stored in the test application rather than the primary application but still use other resources in the primary application.
What I've done to accomplish this (in a not very elegant way) is to copy the test fixture onto my device (or emulated device.) I named it "cleantestdatabase.db." Then in the test code, I copy it to "testdatabase.db," so that I can modify it with my tests but reset it to a known state. Here's the code:
copyFile("cleantestdatabase.db", "testdatabase.db");
private void copyFile(String source, String dest) throws IOException{
String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath() + getActivity().getString(R.string.default_dir);
File newDir = new File(rootPath);
boolean result = newDir.mkdir();
if(result == false){
Log.e("Error", "result false");
}
InputStream in = new FileInputStream(rootPath + source);
File outFile = new File(rootPath + dest);
if(outFile.exists()) {
outFile.delete();
}
outFile.createNewFile();
OutputStream out = new FileOutputStream(outFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With