如何在单元测试中获取上下文以在内存数据库对象中创建 Room 数据库

Cha*_*hna 8 android unit-testing kotlin koin

我正在尝试在执行数据库插入的应用程序存储库类中测试这个函数。我正在Koin用作我的依赖注入库。为了进行测试,我需要创建一个内置于内存的数据库版本。要创建该数据库,我需要 Android 应用程序上下文。所以我创建了我的测试类,如下所示。

import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry
import com.chathuranga.shan.mycontacts.di.applicationModule
import com.chathuranga.shan.mycontacts.di.repositoryModule
import com.chathuranga.shan.mycontacts.room.AppDatabase
import org.junit.After
import org.junit.Test

import org.junit.Before
import org.junit.Rule
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.loadKoinModules
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.dsl.module
import org.koin.test.KoinTest
import org.koin.test.inject
import org.mockito.MockitoAnnotations

class ContactRepositoryTest : KoinTest {

    private val contactRepository: ContactRepository by inject()
    private lateinit var appDatabase: AppDatabase

    @get:Rule
    val rule = InstantTaskExecutorRule()

    @Before
    fun setUp() {

        startKoin {
            printLogger()
            modules(listOf(applicationModule,repositoryModule))
        }

        MockitoAnnotations.initMocks(this)

        val context = ApplicationProvider.getApplicationContext<Context>()
        //val instrumentationContext = InstrumentationRegistry.getInstrumentation().targetContext

        appDatabase = Room
            .inMemoryDatabaseBuilder(context, AppDatabase::class.java)
            .allowMainThreadQueries()
            .build()

        loadKoinModules(module { single(override = true) { appDatabase } })
    }

    @Test
    fun insertContact() {

        val firstName = "Chathuranga"
        val secondName = "Shan"
        val phone = "07711247890"

        contactRepository.insertContact(firstName,secondName,phone,null,null)

    }

    @After
    fun tearDown() {
        stopKoin()
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到了这个例外。

java.lang.IllegalStateException:未注册检测!必须在注册检测下运行。

如您所见,我尝试了两种获取方式Context(检查上面课程中的注释行),但都以同样的方式失败。错误指向我创建Context对象的地方。这个test文件夹中的测试类不在androidTest文件夹中。我想把这个函数和其他将来会出现的函数分开,并在这个类中测试。

这是我的依赖项

//Testing
testImplementation 'junit:junit:4.12'
testImplementation "org.mockito:mockito-core:2.21.0"
testImplementation 'android.arch.core:core-testing:1.1.1'
testImplementation 'androidx.test:core:1.2.0'
testImplementation 'org.koin:koin-test:2.0.1'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
Run Code Online (Sandbox Code Playgroud)

我的依赖注入类。

val applicationModule = module {
    single { AppDatabase.getDatabaseInstance(androidContext().applicationContext) }
}

val activityModule = module {

    scope(named<MainActivity>()) {
        scoped { (activity: MainActivity) ->
            Navigation
                .findNavController(activity, R.id.hostFragment)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我是测试新手。如果我已经掌握了单元测试的概念,请指出。否则指出此代码的问题。谢谢。

Ada*_*itz 5

在本地单元测试中使用 Robolectric 创建上下文

对于在 JVM 上运行的本地单元测试,Robolectric 有效。如果这是在仪器测试中,则不需要 Robolectric。InstrumentationRegistry可以在Joe Birch 的示例中使用

1. 添加库

JUnit 5

构建.gradle

testImplementation "org.robolectric:robolectric:X.X.X"
testImplementation "androidx.test.ext:junit:X.X.X"
Run Code Online (Sandbox Code Playgroud)

结界 4

内置使用 JUnit 4 和 AndroidX 库。

2. 创建应用上下文 ApplicationProvider

结界 5

请参阅:构建本地单元测试 >包含框架依赖项- Android 文档

SomeTest.kt

import androidx.test.core.app.ApplicationProvider

@RunWith(RobolectricTestRunner::class)
class SomeTest {

    @Test
    fun someTest() {
        val appContext = ApplicationProvider.getApplicationContext<Context>()
        ...
    }

}


Run Code Online (Sandbox Code Playgroud)

JUnit 4

请参阅:Robolectric 的文档

3. 使用类注解处理 SDK 29/Java 9 错误 @Config

请参阅:如何将 Java 9 添加到 Android Studio?- 堆栈溢出

  • 为什么不使用“InstrumentationRegistry.getInstrumentation().context”? (2认同)