如何在单元测试中获取上下文以在内存数据库对象中创建Room数据库 [英] How to get Context in unit test to create Room database in memory database object

查看:409
本文介绍了如何在单元测试中获取上下文以在内存数据库对象中创建Room数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在执行数据库插入的应用程序存储库类中测试此功能.我正在使用Koin作为依赖项注入库.为了进行测试,我需要创建一个内置在内存中的数据库版本.要创建该数据库,我需要Android应用程序上下文.因此,我创建了如下的测试类.

I'm trying to test this one function in my application repository class which performs a database insertion. I'm using Koin as my dependency injection library. To do the testing I need to create a Database version that gets built in memory. To create that database I need the Android application context. So I created my test class like below.

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()
    }
}

我正在得到这个例外.

java.lang.IllegalStateException:未注册任何工具!必须在注册工具下运行.

如您所见,我尝试了两种获取Context的方法(请检查上述类中的注释行),但两种方法均以相同的方式失败.错误指向我创建Context对象的地方.此测试类位于test文件夹中,而不位于androidTest文件夹中.我想将此功能与将来将要使用的其他功能分开,并在本课程中进行测试.

As you can see I tried two ways to get Context (check the commented line in above class) and both failed the same way. And error pointed to the place where I create Context object. This test class in test folder not in androidTest folder. I want to separate this function and other functions that gonna come in the future and test in this class.

这是我的依赖项

//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'

我的依赖项注入类.

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

val activityModule = module {

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

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

I'm new to testing. If the way I have grasped the concept of unit testing please point it out. Otherwise Point out the problem with this code. Thanks.

推荐答案

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

对于在JVM上运行的本地单元测试,Robolectric可以工作.如果这是在仪器测试中,则不需要Robolectric. InstrumentationRegistry可以用于乔·伯奇的样本.

build.gradle

testImplementation "org.robolectric:robolectric:X.X.X"
testImplementation "androidx.test.ext:junit:X.X.X"

  • 入门-Robolectric
  • AndroidX Gradle依赖项-Android文档
    • Getting Started - Robolectric
    • AndroidX Gradle dependenceies - Android documentation
    • 内置与JUnit 4和AndroidX库结合使用.

      Built-in use with JUnit 4 and AndroidX library.

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

      See: Build local unit tests > Include framework dependencies - Android documentation

      SomeTest.kt

      import androidx.test.core.app.ApplicationProvider
      
      @RunWith(RobolectricTestRunner::class)
      class SomeTest {
      
          @Test
          fun someTest() {
              val appContext = ApplicationProvider.getApplicationContext<Context>()
              ...
          }
      
      }
      
      
      

      JUnit 4

      请参阅:Robolectric的文档

      JUnit 4

      See: Robolectric's documentation

      请参阅:如何将Java 9添加到Android Studio?-StackOverflow

      See: How to add Java 9 to Android Studio? - StackOverflow

      这篇关于如何在单元测试中获取上下文以在内存数据库对象中创建Room数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆