Testing Room Database in Android using JUnit

17 Mar, 2021
In this article, we are going to test the Room Database in android. Here we are using JUnit to test our code. JUnit is a “Unit Testing” framework for Java Applications which is already included by default in android studio. It is an automation framework for Unit as well as UI Testing. It contains annotations such as @Test, @Before, @After, etc. Here we will be using only @Test annotation to keep the article easy to understand. Note that we are going to implement this project using the Kotlin language.
Step 1: Create a new project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.
Step 2: Add Dependencies
Inside build.gradle (project) add the following code under dependencies. It contains dependencies of Room Db, Coroutiene, JUnit, Truth, and others.
implementation “org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1”
implementation “androidx.room:room-runtime:2.2.6”
implementation “androidx.legacy:legacy-support-v4:1.0.0”
kapt “androidx.room:room-compiler:2.2.6”
implementation “androidx.room:room-ktx:2.2.6”
testImplementation “androidx.arch.core:core-testing:2.1.0”
testImplementation “androidx.room:room-testing:2.2.6”
testImplementation “junit:junit:4.13.2”
testImplementation “com.google.truth:truth:1.1.2”
testImplementation “org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.4”
testImplementation ‘org.robolectric:robolectric:4.5.1’
androidTestImplementation “androidx.test.ext:junit-ktx:1.1.2”
androidTestImplementation “androidx.test.espresso:espresso-core:3.3.0”
androidTestImplementation “com.google.truth:truth:1.1.2”
androidTestImplementation “androidx.arch.core:core-testing:2.1.0”
androidTestImplementation “androidx.test:rules:1.3.0”
androidTestImplementation “androidx.test:runner:1.3.0”
androidTestImplementation “androidx.test:core-ktx:1.3.0”
Before Writing our test lets first create Room Database
Step 3: Create a new model class “Language.kt”
Create a new class “Language.kt” and annotate it with @Entity and pass the table name.
Kotlin
import androidx.room.Entityimport androidx.room.PrimaryKey  @Entity(tableName = "language")data class Language(    val languageName : String="",    val experience : String="") {    @PrimaryKey(autoGenerate = true)    var id : Long=0}
Step 4: Create dao interface
Create a new class “LanguageDao.kt” and annotate it with @Dao.Comments are added for a better understanding of the code.
Kotlin
import androidx.room.Daoimport androidx.room.Insertimport androidx.room.Query  @Daointerface LanguageDao {    // Write two functions one for adding language to the database     // and another for retrieving all the items present in room db.    @Insert    suspend fun addLanguage(language: Language)      @Query("SELECT * FROM language ORDER BY languageName DESC")    suspend fun getAllLanguages(): List<Language>}
Step 5: Create a Database class
Create a new abstract class “LanguageDatabase.kt” and annotate it with @Database. Below is the code of LanguageDatabase.kt class comments are added for better understanding.
Kotlin
import android.content.Contextimport androidx.room.Databaseimport androidx.room.Roomimport androidx.room.RoomDatabase  @Database(entities = [Language::class] , version = 1)abstract class LanguageDatabase : RoomDatabase() {      // get reference of the dao interface that we just created    abstract fun getLanguageDao() : LanguageDao      companion object{        private const val DB_NAME = "Language-Database.db"                  // Get reference of the LanguageDatabase and assign it null value        @Volatile        private var instance : LanguageDatabase? = null        private val LOCK = Any()          // create an operator fun which has context as a parameter        // assign value to the instance variable        operator fun invoke(context: Context) = instance ?: synchronized(LOCK){            instance ?: buildDatabase(context).also{                instance = it            }        }        // create a buildDatabase function assign the required values        private fun buildDatabase(context: Context) = Room.databaseBuilder(            context.applicationContext,            LanguageDatabase::class.java,            DB_NAME        ).fallbackToDestructiveMigration().build()    }}
Step 6: Create a Test class
In order to create a test class of LanguageDatabase.kt right-click on LanguageDatabase then click generate and then select the test. A dialog will open, from the dialog choose Testing library as JUnit4 and keep the class name as default that is LanguageDatabaseTest, and click ok. After that, another dialog will open to choose the destination directory, choose the one which has ..app\src\AndoidTest\. because our test class requires context from the application. Below is the screenshot to guide you create the test class.
Step 7: Working with LanguageDatabaseTest.kt class
Go to LanguageDatabaseTest.kt file and write the following code. Comments are added inside the code to understand the code in more detail.
Kotlin
import android.content.Contextimport androidx.room.Roomimport androidx.test.core.app.ApplicationProviderimport androidx.test.ext.junit.runners.AndroidJUnit4import com.google.common.truth.Truth.assertThatimport junit.framework.TestCaseimport kotlinx.coroutines.runBlockingimport org.junit.*import org.junit.runner.RunWith  @RunWith(AndroidJUnit4::class) // Annotate with @RunWithclass LanguageDatabaseTest : TestCase() {    // get reference to the LanguageDatabase and LanguageDao class    private lateinit var db: LanguageDatabase    private lateinit var dao: LanguageDao      // Override function setUp() and annotate it with @Before    // this function will be called at first when this test class is called    @Before    public override fun setUp() {        // get context -- since this is an instrumental test it requires        // context from the running application        val context = ApplicationProvider.getApplicationContext<Context>()        // initialize the db and dao variable         db = Room.inMemoryDatabaseBuilder(context, LanguageDatabase::class.java).build()        dao = db.getLanguageDao()    }      // Override function closeDb() and annotate it with @After    // this function will be called at last when this test class is called    @After    fun closeDb() {        db.close()    }      // create a test function and annotate it with @Test     // here we are first adding an item to the db and then checking if that item     // is present in the db -- if the item is present then our test cases pass    @Test    fun writeAndReadLanguage() = runBlocking {        val language = Language("Java", "2 Years")        dao.addLanguage(language)        val languages = dao.getAllLanguages()        assertThat(languages.contains(language)).isTrue()    }}
Step 8: Run Tests
To run the test case click on the little run icon near the class name and then select Run LanguageDatabaseTest. If all the test cases pass you will get a green tick in the Run console. In our case, all tests have passed.
Github Repo here.
Android
Kotlin
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.