Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I transfer a database test fixture to device from my unit test application

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!

like image 711
Jeff Axelrod Avatar asked Sep 24 '10 21:09

Jeff Axelrod


People also ask

Should unit tests interact with database?

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.

Can you unit test a database?

While unit testing a database might not be as common or familiar as unit testing application code, it's perfectly achievable!

What are instrumented tests?

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.


2 Answers

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.

like image 115
Alex Pretzlav Avatar answered Nov 15 '22 08:11

Alex Pretzlav


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();
}
like image 39
Jeff Axelrod Avatar answered Nov 15 '22 08:11

Jeff Axelrod