I am currently writing tests for my Android application using Hilt. The App got a Room database, which I want to use in my test classes. Furthermore, I want in some test classes an empty database and in others a database with test values. My question is if I can define in my Test, which provider (empty/full DB) is used for all injections that are happening in the test class?
I tried using the @Named annotation, Qualifiers, and @BindValue. With the first two I am able to use the correct provider for my database, but I do not know how this could be used when injecting my repository. With @BindValue I am not sure if this can be used for this at all.
Here is some simplified code of my problem:
TestDatabaseModule:
@Module
@TestInstallIn(components = SingletonComponent.class, replaces = DatabaseModule.class)
public class TestDatabaseModule {
// Provide empty DB
@Singleton
@Provides
AppDatabase provideInMemoryDbEmpty(@ApplicationContext Context context) {
return Room.inMemoryDatabaseBuilder(context, AppDatabase.class).build();
}
// Provide populated DB
@Singleton
@Provides
AppDatabase provideInMemoryDbFull(@ApplicationContext Context context, Provider<AppDatabase> databaseProvider) {
// AppDatabasePopulateCallback adds some test data
return Room.inMemoryDatabaseBuilder(context, AppDatabase.class).addCallback(new AppDatabasePopulateCallback(databaseProvider)).build();
}
}
Module providing DAO and repository
@InstallIn(SingletonComponent.class)
@Module
public class AccessModule {
@Singleton
@Provides
MyDao provideMyDao(AppDatabase appDatabase) {
return appDatabase.myDao();
}
@Provides
MyRepository providesMyRepository(MyDao myDao) {
return new MyRepository(myDao);
}
}
Test Class one:
@HiltAndroidTest
@SmallTest
public class TestOne {
@Rule
public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
@Rule
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
// Inject repository that uses empty DB
@Inject
MyRepository myRepository;
@Before
public void createDb() {
hiltRule.inject();
}
@Test
public void testOne() {
// Use my repository with the empty database
}
Test class two:
@HiltAndroidTest
@SmallTest
public class TestTwo {
@Rule
public HiltAndroidRule hiltRule = new HiltAndroidRule(this);
@Rule
public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
// Inject repository that uses populated DB
@Inject
MyRepository myRepository;
@Before
public void createDb() {
hiltRule.inject();
}
@Test
public void testTwo() {
// Use my repository with the full database
}
So in the TestOne class, I want to use the repository that can access the empty database, and in the TestTwo class the repository that uses the database with test data.
I know I could populate the database in every test I want to use the data. That is what I will do if it is not possible with Hilt. I am glad for any advice to solve my problem or someone answering that I am on the wrong track if it is not possible.
Thank you!