Closed techeretic closed 3 years ago
@TestInstallIn
only works with @HiltAndroidTest
, but since your TestApplication
extends your MainApplication
you are using it with @HiltAndroidApp
. The reason this works this way is that the way we distinguish test vs prod is with those annotations on the root (they generate different code in the Application
). You'll have to use the @CustomTestApplication
(https://dagger.dev/hilt/testing#custom-test-application) to write your test.
How do I use @CustomTestApplication
with our application implementation?
@CustomTestApplication
forces to be used on an interface which doesn't have the dagger graph that we need to be created in attachBaseContext
. This dagger graph feeds into a module that is used with the hilt singleton component.
@CustomTestApplication
takes in a base class as an argument to the annotation. So you can use @CustomTestApplication(MainApplication::class)
and the test application we generate will subclass your MainApplication
.
Actually, as written, you'll need to do a little refactoring, which is to separate the @HiltAndroidApp
part off of the MainApplication
since it is incompatible with @HiltAndroidTest
. So something like...
@HiltAndroidApp
class MainApplication : MainApplicationImpl
// This class has all of the current logic with your custom Dagger component
open class MainApplicationImpl : Application
@CustomTestApplication(MainApplicationImpl::class)
interface CustomTest
Then setup your tests to use the generated CustomTest_Application
Ah! Lemme try it out.
I was attempting
@CustomTestApplication(MainApplication::class)
interface CustomApplication
and ran into this
public abstract interface CustomApplication {
^
@CustomTestApplication value cannot be annotated with @HiltAndroidApp. Found: com.bug.hiltrobolectricissue.MainApplication
[Hilt] Processing did not complete. See error above for details.
FAILURE: Build failed with an exception.
Thanks for explaining that I have to separate it out.
That fixed it!
Thanks!
I've updated the Example project with the changes that fixed it. See commit here https://github.com/techeretic/HiltRobolectricIssue/commit/22ff8e9534fe21f05126bd808779a18bf6af5a15
One thing to call out is that I had to move out all the field injection from the MainApplication
to the class that has the @HiltAndroidApp
. Though this can worked around.
I'll continue with our app migration to hilt from dagger 2
So, we have a complicated dagger2 app structure along with multiple dynamic feature modules. I have created a sample project : https://github.com/techeretic/HiltRobolectricIssue that explains this issue. Before I dive into the details, let me give some background about the app
Application.attachBaseContext
method.DynamicFeatureDependencies
EntryPoint which we'll used to share dependencies with the dagger component in the dynamic feature moduleNow, since robolectric tests aren't supported in a dyamic feature modules, we create a separate Android Library just for running the robolectric tests. This library depends on the app module and the dynamic feature module.
In robolectrictests module, we have configured a robolectric test runner to run with the a custom app (because we have some custom setups being done in our implementation of the Application class).
and TestApplication is
We have a
SingletonModule
that provides an implementation ofSingletonInterface
For testing, we setup a test implementation of the
SingletonInterface
for our robolectric testEventually, when we run the test as
It fails.
Thus, the
TEST_VALUE
which is being set inTestSingletonModule
is never part of the hilt singleton dagger graph.So, either this
TestInstallIn
doesn't work when using custom application implementation (not the @CustomTestApplication) andEntryPoints
used for sharing dependencies with a Dagger2 graph in a dynamic feature module.(Note: Code snippets here are from a project https://github.com/techeretic/HiltRobolectricIssue that mimics our app code.)