Donal Rafferty
Donal Rafferty

Reputation: 19826

Android - Robolectric testing With RxAndroid?

I am trying to use Robolectric to test my Android application but have come across a testing issue I can't get my head around.

I am testing an Activity which extends my BaseActivity class and uses RxAndroid, that class looks like this:

public abstract class BaseActivity extends AppCompatActivity {
    protected final SharedService sharedService = MyApplication.getInstance().getSharedService();

    protected Activity getActivity() {
        return this;
    }
}

As you can see it gets a sharedService object from my Application base class.

In my Activity I then reference this code as follows:

//...
        Subscription s = sharedService.login(params)
            .compose(ObservableUtils.<JsonObject>applySchedulers())
            .subscribe(new Action1<JsonObject>() {
                @Override
                public void call(JsonObject jsonObject) {
                    //...
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    //...
                }
            });

    subscriptions.add(s);

//..

So the Activity directly references the sharedService variable from the BaseActivity to access it and call a method on the SharedService Object. It uses RxAndroid to get an observable.

The code in the Retrofit call is as follows:

@POST("/login")
Observable<JsonObject> login(
        @Body JsonObject body) ;

The problem is when I come to test using Robolectric I get a null pointer exception in the Activity where when the RxAndroid code is called.

My test is as follows:

@Config(constants = BuildConfig.class)
@RunWith(TestRunner.class)
public class MyActivityTest{

@Mock
private SharedService mockSharedService;

@Before
    public void setup() {
        // Convenience method to run Activity through the Activity Lifecycle methods:
        // onCreate(...) => onStart() => onPostCreate(...) => onResume()

        MockitoAnnotations.initMocks(this);

        TestMyApplication testMyApp = (TestMyApplication) TestCompanionApplication.getInstance();
        testMyApp.setSharedService(this.mockSharedService); //Set our Mocked application class to use our mocked API

        //Build our activity using Robolectric
        ActivityController<MyActivity> controller = Robolectric.buildActivity(MyActivity.class);
        activity = controller.get();

        controller.create(); //Create out Activity

        //..Get views
}

@Test
public void testService(){

    btnTest.click(); //This fires the service call
    Mockito.verify(this.mockSharedService).login((JsonObject) Mockito.any());

}

When I run this test I get the NullPointerException.

So I know that I somehow need to get the Activity to use the mocked API that I have set on the TestMyApplication class, but since the BaseActivity creates a variable that holds this and then my other Activities reference this how do I do this with Robolectric?

Upvotes: 1

Views: 258

Answers (1)

Eugen Martynov
Eugen Martynov

Reputation: 20130

It is quite easy to fix:

when(mockSharedService.login(any())).thenReturn(Observable.just(new JsonObject()));

But it will probably fail later where you're trying to process received json.

Upvotes: 1

Related Questions