I'm trying to use Dagger 2 for DI in my Android instrumentation tests. It works perfectly fine for Classes/Activities/Fragments in the main application component, but my test component seems to be missing some bindings I can't find. Any ideas on how to go about it would be appreciated. The code I have looks like this:
AssetRepositoryTest
public class AssetRepositoryTest {
@Nested
@DisplayName("Given a populated database")
public class PopulatedDatabaseInstance {
@Inject
private TestDatabase database;
@Inject
private AssetRepository repository;
@BeforeEach
public void setup() {
final TestApplication application = ApplicationProvider.getApplicationContext();
application.androidInjector().inject(this);
// Setup database
}
// Tests
}
}
Running the instrumentation tests I get the following exception:
java.lang.IllegalArgumentException: No injector factory bound for Class<AssetRepositoryTest.PopulatedDatabaseInstance>
And the dagger related code is as follows:
TestComponent
@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
TestPersistenceModule.class
})
public interface TestComponent extends AndroidInjector<TestApplication> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<TestApplication> {
}
}
TestPersistenceModule
@Module(includes = TestRoomModule.class)
public abstract class TestPersistenceModule {
@Binds
abstract AssetRepository bindAssetRepository(final AssetRepositoryImpl repository);
}
TestRoomModule
@Module
public class TestRoomModule {
@Provides
@Singleton
TestDatabase provideTestDatabase(final Application application) {
return Room.inMemoryDatabaseBuilder(application, TestDatabase.class).build();
}
@Provides
@Singleton
AssetDao provideAssetDao(final TestDatabase testDatabase) {
return testDatabase.getAssetDao();
}
}
TestApplication
public class TestApplication extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerTestComponent.builder().create(this);
}
}
Besides that, I've a custom AndroidJUnitRunner
extension class that overrides the newApplication
method and return a TestApplication
instance for the test cases.
My AssetRepositoryImpl
is as follows:
AssetRepositoryImpl
@Singleton
public class AssetRepositoryImpl extends AbstractRepository<Asset, AssetEntity> implements AssetRepository {
@Inject
protected WorkspaceDao workspaceDao;
@Inject
public AssetRepositoryImpl(final AssetDao dao, final AssetMapper mapper) {
super(dao, mapper);
}
}
The classes that I haven't pasted here have @Inject
annotations in their constructors and this code is working properly in the main application with the respective main modules and components.
As a final thought, the AssetRepositoryTest.PopulatedDatabaseInstace
, which is instantiated by JUnit, is therefore not instantiated by Dagger and, to my knowledge, that seems to be the problem here.
How can I tell Dagger how to inject these fields into my JUnit test class?