24

I need both Robolectric and Mockito in my test, each one proposes their own TestRunner, what do I do?

I have this code:

@RunWith(MockitoJUnitRunner.class)
@EBean
public class LoginPresenterTest {

    @Bean
    LoginPresenter loginPresenter;

    @Mock
    private LoginView loginView;

    @AfterInject
    void initLoginPresenter() {
        loginPresenter.setLoginView(loginView);
    }

    @Test
    public void whenUserNameIsEmptyShowErrorOnLoginClicked() throws Exception {
        when(loginView.getUserName()).thenReturn("");
        when(loginView.getPassword()).thenReturn("asdasd");
        loginPresenter.onLoginClicked();
        verify(loginView).setEmailFieldErrorMessage();
    }
}

The problem is AndroidAnnotations doesn't inject the dependencies and I get a NPE when trying to use LoginPresenter

Someone told me to use the LoginPresenter_ constructor, so that I can force inject the dependency myself this way:

LoginPresenter loginPresenter = LoginPresenter_.getInstance_(context);

In order to gain access to the context, I had to switch from Unit Tests to Android Instrumentation Tests and do getInstrumentation().getTargetContext() but I want Unit Tests, and not Instrumentation ones.

So another person told me to use Robolectric for that - it is supposed to be able to provide me with an Application context.

However, when I looked at the getting started page of Robolectric, it says

@RunWith(RobolectricGradleTestRunner.class)

which is going to clash with my current @RunWith annotation for Mockito, so what do I do?

Kaloyan Roussev
  • 14,515
  • 21
  • 98
  • 180

1 Answers1

41

Use the Robolectric runner. Robolectric uses its own classloader that favors its replacements for the Android API, so it really does need to handle classloading on its own. There's no other way to use Robolecric.

There are several ways to initialize Mockito (see this SO answer), that are strictly equivalent to using the runner, but the two that make the most sense for your case are:

  • Using MockitoRule, because you're already on JUnit4:

    @Rule public MockitoRule rule = MockitoJUnit.rule();
    
  • Creating manual @Before and @After methods:

    @Before public void setUpMockito() {
      MockitoAnnotations.initMocks(this);
    }
    
    @After public void tearDownMockito() {
      Mockito.validateMockitoUsage();
    }
    
Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251