Prokky Prokky - 4 months ago 65
Android Question

Robolectric app testing with Firebase

I'm trying to write a simple Robolectric test for my presenter, which uses the Firebase Database and Firebase Auth. But every time I'm trying to start the test, it throwes an IllegalStateException.

java.lang.IllegalStateException: FirebaseApp with name [DEFAULT] doesn't exist.
at com.google.firebase.FirebaseApp.getInstance(Unknown Source)
at com.google.firebase.FirebaseApp.getInstance(Unknown Source)
at com.google.firebase.auth.FirebaseAuth.getInstance(Unknown Source)


My test is quite simple

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class LoginPresenterTest {
private LoginPresenter presenter;
private LoginMvpView view;

@Before
public void beforeEachTest() {
presenter = new LoginPresenter();
view = new LoginFragment();
}

@Test
public void attachView_shouldAttachViewToThePresenter() {
presenter.attachView(view);
assertSame(presenter.getMvpView(), view);
}
}


While in my presenter constructor I just get the Firebase instances.

public LoginPresenter() {
this.firebaseAuth = FirebaseAuth.getInstance();
this.database = FirebaseDatabase.getInstance().getReference();
}


Is there any way to use the Robolectric with Firebase?

Answer

If you don't use them in your code to test it is possible to inject them by constructor:

public LoginPresenter(FireBaseAuth firebaseAuth, FirebaseDatabase database){
    this.firebaseAuth = firebaseAuth;
    this.database = database;
}

and you inject null for them, remember this is a very poor way by using null. The much better way is to use a library like Mockito or use interfaces/wrapper etc.

E.g. use an interface

public interface IDatabase {
    public List<String> getData();
}

The LoginPresenter:

public LoginPresenter(FireBaseAuth firebaseAuth, IDatabase database){
    this.firebaseAuth = firebaseAuth;
    this.database = database;
}

The normal implementation of the IDatabase:

public class MyDatabase implements IDatabase {

    private FirebaseDatabase database;

    public MyDatabase(FirebaseDatabase database) {
        this.database = database;
    }

    public List<String> getDate() {
        // Use the FirebaseDatabase for returning the getData
        return ...;
    }
}

And now it is very easy to mock the database by using the IDatabase:

public class DatabaseMock implements IDatabase {
    public List<String> getData() {
        // Return the expected data from the mock
        return ...;
    }
}

Call it from the test like:

 presenter = new LoginPresenter(FirebaseAuth.getInstance(), new DatabaseMock());
Comments