Reputation: 18889
With the latest Dagger2 we can inject dependencies through the following code:
public class BaseActivity extends LifecycleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
}
}
Other activities that require DI inherit from this BaseClass. For my instrumentation tests, I don't want to use Dagger, I can just mock the objects.
My setup for the instrumentation test (I'm currently testing LoginActivity, which extends BaseActivity) is not special and as follows:
TestRunner:
public class LivefeedTestRunner extends AndroidJUnitRunner{
@Override
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return super.newApplication(cl, TestApp.class.getName(), context);
}
}
TestApp:
public class TestApp extends Application {
@Override
public void onCreate() {
super.onCreate();
}
}
The problem is that running the instrumentation test results in an error caused by:
Caused by: java.lang.RuntimeException: com.example.kimgysen.livefeed_v002.TestApp does not implement dagger.android.HasActivityInjector at dagger.android.AndroidInjection.inject(AndroidInjection.java:48) at com.example.kimgysen.livefeed_v002.ui.BaseActivity.onCreate(BaseActivity.java:12) at com.example.kimgysen.livefeed_v002.ui.login.LoginActivity.onCreate(LoginActivity.java:32) at android.app.Activity.performCreate(Activity.java:6237) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) at android.support.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:624) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) ... 9 more
Which points to the following line:
public class BaseActivity extends LifecycleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this); // <-- this line
super.onCreate(savedInstanceState);
}
}
Any idea how I can easily bypass this?
In my app itself, I implement dagger.android.HasActivityInjector
, but I don't need it for my instrumentation test.
Upvotes: 1
Views: 1047
Reputation: 5020
There is an alternative solution in the android-architecture-components samples on Github.
They inject the activities trough ActivityLifecycleCallbacks. For instrumented tests they use a TestApp that does not register ActivityLifecycleCallbacks so it injects nothing.
See https://stackoverflow.com/a/48101811/1552622.
Upvotes: 0
Reputation: 18889
I solved the problem by creating a fake activityInjector as suggested in the following post:
https://github.com/google/dagger/blob/master/javatests/dagger/android/AndroidInjectionTest.java#L60
(equivalent for fakeActivityInjector)
public class TestApp extends Application implements HasActivityInjector {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public AndroidInjector<Activity> activityInjector() {
return fakeActivityInjector("injected by app");
}
public static class InjectableActivity extends Activity {
String tag;
}
private static AndroidInjector<Activity> fakeActivityInjector(String tag) {
return instance -> {
if (instance instanceof InjectableActivity) {
((InjectableActivity) instance).tag = tag;
}
};
}
}
Upvotes: 4