I'm using Hilt to inject some dependencies like so:
@Module
@InstallIn(SingletonComponent::class)
object SomethingModule {
@Provides
fun provideSomething(@ApplicationContext context: Context): Something {
//return RealSomething
}
}
I want to replace this binding in my tests and following this guide I added this fake module to the same folder as my instrumented test:
@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [SomethingModule::class]
)
object FakeSomethingModuleModule {
@Provides
fun provideSomethingModule(): Something {
return FakeSomething()
}
}
When I try to run my instrumented test the build fails with a duplicate binding error:
error: [Dagger/DuplicateBindings] com.example.Something is bound multiple times:
public abstract static class SingletonC implements HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,
Commenting out the Fake Module fixes the issue. Anyone see what I'm missing here?
EDIT: Just tried with @UninstallModules
and ran into the same build error:
@UninstallModules(SomethingModule::class)
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class MyInstrumentedTest {
@Module
@InstallIn(SingletonComponent::class)
object FakeSomethingModule {
@Provides
fun provideSomthing(): Something = FakeSomething()
}
I tried lots of different things in order to finally get to a solution:
Make sure the fake implementations have @Inject constructor()
In the test @Module
use @Binds
and an abstract class instead of @Provides
You don't need a component that combines all your modules, this code is not necessary:
@Module(
includes = [ <modules> ]
@Module(includes = SomethingBinding)
. I created a module just for the object I wanted to mock in my instrumented tests