在本文中,我们将在android中测试Room数据库。在这里,我们使用JUnit来测试我们的代码。 JUnit是Java应用程序的“单元测试”框架,默认情况下已包含在android studio中。它是单元和UI测试的自动化框架。它包含注释,比如@测试,@Before,@After等等,下面我们将只使用@Test注解让文章很容易理解。请注意,我们将使用Kotlin语言实施此项目。
分步实施
步骤1:创建一个新项目
要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Kotlin作为编程语言。
步骤2:添加依赖项
在build.gradle(项目)内部,在依赖项下添加以下代码。它包含Room Db,Coroutiene,JUnit,Truth等的依赖项。
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”
在编写测试之前,首先要创建房间数据库
第3步:创建一个新的模型类“ Language.kt”
创建一个新的类“ Language.kt ”,并用@Entity对其进行注释并传递表名。
Kotlin
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "language")
data class Language(
val languageName : String="",
val experience : String=""
) {
@PrimaryKey(autoGenerate = true)
var id : Long=0
}
Kotlin
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
@Dao
interface 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
}
Kotlin
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import 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()
}
}
Kotlin
import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import junit.framework.TestCase
import kotlinx.coroutines.runBlocking
import org.junit.*
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class) // Annotate with @RunWith
class 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()
// 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()
}
}
步骤4:创建Dao接口
创建一个新的类“ LanguageDao.kt ”,并使用@Dao对其进行注释。添加了注释以更好地理解代码。
科特林
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
@Dao
interface 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
}
步骤5:创建一个数据库类
创建一个新的抽象类“ LanguageDatabase.kt ”,并使用@Database对其进行注释。下面是添加的LanguageDatabase.kt类注释的代码,以使您更好地理解。
科特林
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import 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()
}
}
步骤6:创建一个测试类
为了创建LanguageDatabase.kt的测试类,请在LanguageDatabase上单击鼠标右键,然后单击“生成”,然后选择测试。将打开一个对话框,从对话框中选择“测试库”作为JUnit4 ,并将类名保留为默认名称,即LanguageDatabaseTest ,然后单击“确定” 。之后,将打开另一个对话框以选择目标目录,然后选择具有..app \ src \ AndoidTest \的目录。因为我们的测试类需要应用程序中的上下文。以下是指导您创建测试类的屏幕截图。
步骤7:使用LanguageDatabaseTest.kt类
转到LanguageDatabaseTest.kt文件并编写以下代码。在代码内部添加了注释,以更详细地了解代码。
科特林
import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.google.common.truth.Truth.assertThat
import junit.framework.TestCase
import kotlinx.coroutines.runBlocking
import org.junit.*
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class) // Annotate with @RunWith
class 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()
// 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()
}
}
步骤8:运行测试
要运行测试用例,请单击类名附近的小运行图标,然后选择运行LanguageDatabaseTest。如果所有测试用例都通过,您将在“运行”控制台中看到一个绿色的勾号。在我们的案例中,所有测试均已通过。
Github Repo在这里。