Testing database on Android: ProviderTestCase2 or RenamingDelegatingContext?

后端 未结 5 2046
[愿得一人]
[愿得一人] 2020-12-13 04:14

I\'ve implemented access to a database using SQLiteOpenHelper from the android.database package within some classes (with pattern DAO).

I wrote some jun

5条回答
  •  眼角桃花
    2020-12-13 05:12

    I actually use database with SQLiteOpenHelper and I have a trick for testing. The idea is to use standard on-file stored DB during the normal use of the app and an in-memory DB during tests. In this way you can use a clear DB for each test without insert/delete/update data in your standard DB. It works fine for me.

    Keep in mind you can use in-memory database, just passing null as name of database file. This is clearly documented in the API documentation.

    Advantages of using in-memory DB during tests is explained here: https://attakornw.wordpress.com/2012/02/25/using-in-memory-sqlite-database-in-android-tests/

    In my project I have the DBHelper class wich extends SQLiteHelper. As you can see, there are the standard methods. I simply added a constructor with two parameters. The difference is that when I call the super constructor, I pass null as DB name.

    public class DBHelper extends SQLiteOpenHelper {
    
        public static final int DATABASE_VERSION = 1;
        public static final String DATABASE_NAME = "mydatabase.db";
    
        public DBHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    
        public DBHelper(Context context, boolean testMode) {
            super(context, null, null, DATABASE_VERSION);
        }
    
        public void onCreate(SQLiteDatabase db) {
            //create statements
        }
    
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            //on upgrade policy
        }
    
        public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            //on downgrade policy
        }
    }
    

    Every "model" in the project extends DBModel that is an abstract class.

    public abstract class DBModel {
        protected DBHelper dbhelper;
    
        public DBModel(Context context) {
            dbhelper = new DBHelper(context);
        }
    
        //other declarations and utility function omitted
    
    }
    

    As discussed here: How can I find out if code is running inside a JUnit test or not? there is a way to establish if you are running JUnit tests, simply searching in stack trace elements. As a conseguence, I modified DBModel constructor

    public abstract class DBModel {
        protected DBHelper dbhelper;
    
        public DBModel(Context context) {
            if(isJUnitTest()) {
                dbhelper = new DBHelper(context, true);
            } else {
                dbhelper = new DBHelper(context);
            }
        }
    
        private boolean isJUnitTest() {
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
            List list = Arrays.asList(stackTrace);
            for (StackTraceElement element : list) {
                if (element.getClassName().startsWith("junit.")) {
                    return true;
                }
            }
            return false;
        }
    
        //other declarations and utility function omitted
    
    }
    

    Note that

    startsWith("junit.")
    

    may be

    startsWith("org.junit.")
    

    in your case.

提交回复
热议问题