Android testing - start with clean database for every test
mDb.delete(DATABASE_TABLE_NAME, null, null);
That is indeed the solution/way-to-go...
I changed the first line in my setUp(..) method to this:
cleanUpDatabase(tableList);
And then I added the method cleanUpDatabse(..) liek this:
private void cleanUpDatabase(List<String> dbTables) {
Log.i(LOG_TAG, "Preparing to clean up database...");
DatabaseHelper dbHelper = new DatabaseHelper(getInstrumentation().getTargetContext());
ConnectionSource cs = dbHelper.getConnectionSource();
SQLiteDatabase db = dbHelper.getWritableDatabase();
Log.i(LOG_TAG, "Dropping all tables");
for (String table : dbTables) {
db.execSQL("DROP TABLE IF EXISTS " + table);
}
Log.i(LOG_TAG, "Executing the onCreate(..)");
dbHelper.onCreate(db, cs);
Log.i(LOG_TAG, "Verifying the data...");
for (String table : dbTables) {
Cursor c = db.query(table, new String[]{"id"}, null, null, null, null, null);
int count = c.getCount();
if (count != 1 && (table.equals("project") || table.equals("task"))) {
dbHelper.close();
Log.e(LOG_TAG, "We should have 1 record for table " + table + " after cleanup but we found " + count + " record(s)");
throw new RuntimeException("Error during cleanup of DB, exactly one record should be present for table " + table + " but we found " + count + " record(s)");
} else if (count != 0 && !(table.equals("project") || table.equals("task"))) {
dbHelper.close();
Log.e(LOG_TAG, "We should have 0 records for table " + table + " after cleanup but we found " + count + " record(s)");
throw new RuntimeException("Error during cleanup of DB, no records should be present for table " + table + " but we found " + count + " record(s)");
}
}
Log.i(LOG_TAG, "The database has been cleaned!");
dbHelper.close();
}
This piece of code gets executed before every test, which makes all my tests independent from each other.
Caution: In order to retrieve a reference to your DatabaseHelper (your own implementation off course ;) ) you cannot call getActivity()
because that will launch your activity (and thus do all your initial DB loading (if any..)
A bit tangential to this problem, but I landed here when I was looking for help. Might be helpful to some folks. If you initialize your database with the RenamingDelegatingContext, it cleans the database between runs.
public class DataManagerTest extends InstrumentationTestCase {
private DataManager subject;
@Before
public void setUp() {
super.setUp();
RenamingDelegatingContext newContext = new RenamingDelegatingContext(getInstrumentation().getContext(), "test_");
subject = new DataManager(newContext);
}
// tests...
}
And the associated DataManagerClass.
public class DataManager {
private SQLiteDatabase mDatabase;
private SQLiteOpenHelper mHelper;
private final String mDatabaseName = "table";
private final int mDatabaseVersion = 1;
protected DataManager(Context context) {
this.mContext = context;
createHelper();
}
private void createHelper() {
mHelper = new SQLiteOpenHelper(mContext, mDatabaseName, null, mDatabaseVersion) {
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// createTable...
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
// upgrade table
}
};
}
...
}
InstrumentationRegistry → getContext → deleteDatabase
android.support.test.InstrumentationRegistry
's getTargetContext and, counterintuitively perhaps, getContext should do the trick:
Synopsis
Use getContext for deleting database (not getTargetContext).
getContext().deleteDatabase(DbHelper.DATABASE_NAME);
Example
public class DbHelperTest {
private DbHelper mDb;
@Before
public void setUp() throws Exception {
getContext().deleteDatabase(DbHelper.DATABASE_NAME);
mDb = new DbHelper(getTargetContext());
}
@After
public void tearDown() throws Exception {
mDb.close();
}
@Test
public void onCreate() throws Exception {
mDb.onCreate(mDb.getWritableDatabase());
}
@Test
public void onUpgrade() throws Exception {
mDb.onUpgrade(mDb.getWritableDatabase(), 1, 2);
}
@Test
public void dropTable() throws Exception {
String tableName = "mesa";
mDb.getReadableDatabase().execSQL("CREATE TABLE "
+ tableName + "(_id INTEGER PRIMARY KEY AUTOINCREMENT)");
mDb.dropTable(mDb.getWritableDatabase(), tableName);
}
}