Как получить Контекст в модульном тесте для создания базы данных Room в памяти объекта базы данных - PullRequest
2 голосов
/ 18 января 2020

Я пытаюсь протестировать эту функцию в своем классе репозитория приложений, который выполняет вставку базы данных. Я использую 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()
    }
}

И я получаю это исключение.

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'

Мой класс внедрения зависимостей.

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

val activityModule = module {

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

Я новичок в тестировании. Если я так понял концепцию модульного тестирования, укажите это. В противном случае укажите на проблему с этим кодом. Спасибо.

...