Skip to content
This repository has been archived by the owner on Aug 2, 2024. It is now read-only.

Inject the right database in instrumentation unit test #719

Open
anastr opened this issue May 26, 2021 · 0 comments
Open

Inject the right database in instrumentation unit test #719

anastr opened this issue May 26, 2021 · 0 comments

Comments

@anastr
Copy link

anastr commented May 26, 2021

I was trying to run PlantDetailViewModelTest but I found there is something going wrong.
In the test, you try to initialize appDatabase in the test while it should be injected.

Is it a problem or bad practice?

It is actually a big problem, if we define an in-memory database in our test, and inject the repository (plantRepository & gardenPlantRepository) that've been provided by Hilt we will have two different database to work on. First our defined in-memory database, second the actual database in our installed-app that've been injected into our repositories, and so passed to viewModel object.
So, the assertion in the test is not valid, because we try to run it against in-app database not the in-memory instance.

How can we make this test fail?

Simply install the app on the emulator, add Apple planet to our garden. Then change the planetId of our test object to malus-pumila (which is the planet_id for Apple planet in app's database), and deploy the test on the same emulator. It will fail.
If our viewModel tries to modify or insert any object to the database it will modify the app database not our testable in-memory database.

What is the solution?

I thing we should replace our DatabaseModule with some fake hilt module like this one:

@Module
@TestInstallIn(
        components = [SingletonComponent::class],
        replaces = [DatabaseModule::class],
)
class FakeDatabaseModule {
    @Singleton
    @Provides
    fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
        // I think injecting ApplicationContext is fine while we are using instrumentation test.
        return Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).build()
    }
    ...
}

And in our test we can simply inject the database object if we have to deal with it (close it maybe).

@Inject
lateinit var appDatabase: AppDatabase

Now our viewModel test will work on a single in-memory database.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
@anastr and others