70090

How to get Context in unit test to create Room database in memory database object

<h3>Question</h3>

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

And I'm getting this exception.

java.lang.IllegalStateException: No instrumentation registered! Must run under registering instrumentation.

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.

Here are my dependencies

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

My dependency injection class.

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.


<h3>Answer1:</h3>
Create Context with Robolectric in a local unit test

For local unit tests run on the JVM, Robolectric works. If this is in an instrumented test, then Robolectric is not needed. InstrumentationRegistry can be used as in Joe Birch's sample.

<h2>1. Add libraries</h2> <h3>JUnit 5</h3>

<em>build.gradle</em>

testImplementation "org.robolectric:robolectric:X.X.X" testImplementation "androidx.test.ext:junit:X.X.X" <ul><li>Getting Started - Robolectric</li> <li>AndroidX Gradle dependenceies - Android documentation</li> </ul><h3>Junit 4</h3>

Built-in use with JUnit 4 and AndroidX library.

<ul><li>testImplementation "androidx.test:core:X.X.X"</li> </ul><h2>2. Create app Context with ApplicationProvider</h2> <h3>Junit 5</h3>

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

<em>SomeTest.kt</em>

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

<em>See: Robolectric's documentation</em>

<h2>3. Handle SDK 29/Java 9 error with class annotation @Config</h2>

<em>See: How to add Java 9 to Android Studio? - StackOverflow</em>

来源:https://stackoverflow.com/questions/59799156/how-to-get-context-in-unit-test-to-create-room-database-in-memory-database-objec

Recommend

  • Kotlin's List missing “add”, “remove”, Map missing “put”, etc?
  • Send array of object inside custom Azure DevOps tasks / extensions
  • Send array of object inside custom Azure DevOps tasks / extensions
  • C++11 calling constructor from constructor of same class type
  • np.random.permutation with seed?
  • TypeScript: subtyping and covariant argument types
  • What is a shaded jar? And what is the difference/similarities between uber jar and shaded jar? [dupl
  • EditText won't write into single line
  • How to use es6 import for images
  • Using Facebook Graph API 2.2 to get like and share count
  • php - remove “code” param in facebook app URL
  • How does a JPA provider access (private) field values when no getter/setter method are defined?
  • composer self-update TransportException
  • Using CompositeItemWriter the writer or classify method is not getting called
  • How to remove light's deflections [closed]
  • python: unpacking a string to a list
  • FB wall posting OAuthException
  • Ansible vault password in group_vars not detected [duplicate]
  • how can i have scrollbar when position is negative?
  • Write and Read from a file
  • Condition on a timestamp column to select data for a year
  • Implicit resolution with covariance
  • angular 2 websql typings
  • 30 tables with few rows - TRUNCATE the fastest way to empty them and reset attached sequences?
  • Combine rows with same id and delete duplicated rows
  • Scrapy + Splash: scraping element inside inner html
  • Accessing Dictionaries VS Accessing Shelves
  • How to use array in autohotkey?
  • Calculate time from document
  • how to snap two objects in runtime in unity?
  • jQuery scrollTop if URL has hash
  • Computing the discrete fourier transform of audio data with FFTW
  • VLOOKUP in IMPORTRANGE