2

I have an app that make some calls to a REST API. I am using Retrofit to implement the API and I am using Roboguice to inject my REST service where needed.

I am trying to write up a test suite using espresso. I want to use a custom injection module so I can mock responses for Retrofit using Mockito.

How can I change my test suite to use a custom injection module from Roboguice keeping espresso.

PS: I've seen how to do this with Roboelectric, but I am not using Roboelectric right now.

Tiago Veloso
  • 8,513
  • 17
  • 64
  • 85

2 Answers2

2

I stumbled upon the same problem and I couldn't find an easy solution for this online. After a day of tries and fails, I finally found a solution which works for me.

You need to declare a custom ActivityTestRule class to override the Application Injector before the activity is launched. Here is an example :

@RunWith(AndroidJUnit4.class)
public class LoginActivityTest {

    protected final Api mApi = mock(Api.class);
    // declare the other mocks you want here
    protected final AbstractModule mTestModule = new MyTestModule();

    @Rule
    public ActivityTestRule<LoginActivity> mActivityRule = new RoboGuiceActivityTestRule<>(LoginActivity.class);

    private class RoboGuiceActivityTestRule<T extends Activity> extends ActivityTestRule<T> {

        public RoboGuiceActivityTestRule(Class<T> activityClass) {
            super(activityClass);
        }

        @Override
        protected void beforeActivityLaunched() {
            RoboGuice.overrideApplicationInjector((Application) InstrumentationRegistry.getTargetContext().getApplicationContext(), mTestModule);
        }
    }

    private class MyTestModule extends AbstractModule {

        @Override
        protected void configure() {
            bind(Api.class).toInstance(mApi);
            // bind the other mocks here
        }
    }

    @Test
    public void checkEmptyFormDoNotPerformLogin() throws Exception {
        onView(withId(R.id.etLogin)).perform(clearText());
        onView(withId(R.id.etPassword)).perform(clearText());
        onView(withId(R.id.btLogin)).perform(click());
        verify(mApi, times(0)).login("", "");
    }

    // ...
}

Of course, you can extract the class and pass the module to the constructor for a cleaner code.

Benjamin M.
  • 604
  • 6
  • 13
0

According to https://github.com/roboguice/roboguice/wiki/Your-First-Testcase, you should call RoboGuice.util.reset() to tear down custom injectors. You can put it

        @Override
        protected void afterActivityFinished() {
            RoboGuice.util.reset();
        }