Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to mock Presenter method in Robolectric ? #79

Open
development-codeface opened this issue Jul 10, 2018 · 4 comments
Open

How to mock Presenter method in Robolectric ? #79

development-codeface opened this issue Jul 10, 2018 · 4 comments

Comments

@development-codeface
Copy link

development-codeface commented Jul 10, 2018

First of all congratulations for the awesome library. I am new in mockito and robolectric, and just exploring the features.
The following test case how we can write using robolectric.

public class MainActivityMockPresenterTest {

@Rule public EspressoDaggerMockRule rule = new EspressoDaggerMockRule();

@Rule public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class, false, false);

@Mock MainPresenter presenter;

@Mock SnackBarManager snackBarManager;

@Test
public void testOnCreate() {
    final MainActivity activity = activityRule.launchActivity(null);

    doAnswer(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            activity.showText("Hello world");
            return null;
        }
    }).when(presenter).loadData();

    onView(withId(R.id.reload)).perform(click());

    onView(withId(R.id.text)).check(matches(withText("Hello world")));
}

@Test
public void testErrorOnCreate() {
    doAnswer(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            snackBarManager.showMessage("Error!");
            return null;
        }
    }).when(presenter).loadData();

    activityRule.launchActivity(null);
    onView(withId(R.id.reload)).perform(click());

    onView(withId(R.id.text)).check(matches(withText("")));

    verify(snackBarManager).showMessage("Error!");
}

}

@fabioCollini
Copy link
Owner

Hi, I have never tried but it should work if you don't use standard Dagger subcomponent. Here you can find an example of a Robolectric test

https://github.com/fabioCollini/DaggerMock/blob/cc0b0acd98941cf432dad9f2771e79bc1e54d5c7/RealWorldAppInjector/src/test/java/it/cosenonjaviste/daggermock/robolectric/MainActivityTest.java

Let me know if you get some errors

@development-codeface
Copy link
Author

development-codeface commented Jul 16, 2018

i have tried this but mocking not happening still it show the original value. Please check my unit test case
presenter

public class MainPresenter {

private MainService mainService;

private MainView view;

private SnackBarManager snackBarManager;

public MainPresenter(MainService mainService, MainView view, SnackBarManager snackBarManager) {
    this.mainService = mainService;
    this.view = view;
    this.snackBarManager = snackBarManager;
}

public void loadData() {
    try {
        String s = mainService.doSomething();
        view.showText(s);
    } catch (Exception e) {
        snackBarManager.showMessage((Activity) view, e.getMessage());
    }
}

public void testPresenter() {
    view.showText(textShow());
}

public String textShow(){
    return "ORGINAL";
}

}

TestRule

@RunWith(RobolectricTestRunner.class)
@config(constants = BuildConfig.class, sdk = 21)
public class MainActivityTest {

@Rule
public final DaggerMockRule<AppComponent> rule = new RobolectricMockTestRule();

@Mock
RestService restService;

MainActivity mainActivity;

@Mock
MainPresenter presenter;



@Test
public void testOnCreate() {
    when(restService.executeServerCall()).thenReturn(true);
    Robolectric.setupActivity(MainActivity.class);
}

@Test
public void testPresenter() {
    when(presenter.textShow()).thenReturn("MOCK");
    Robolectric.setupActivity(MainActivity.class);
    MainActivity mainActivityVal = Robolectric.setupActivity(MainActivity.class);
    TextView results = (TextView) mainActivityVal.findViewById(R.id.text);
    Button button = (Button) mainActivityVal.findViewById(R.id.reload);
    button.performClick();
    Assert.assertEquals("MOCK",mainActivityVal.presenter.textShow());
}

}

@development-codeface
Copy link
Author

development-codeface commented Jul 17, 2018

I have done one work around, please let me know this approach is acceptable.
@rule
public final DaggerMockRule rule = new RobolectricMockTestRule();

@Mock
RestService restService;

MainActivity mainActivity;

@Mock
MainPresenter presenter;


@Before
public void beforemoke() {
    //when(restService.executeServerCall()).thenReturn(true);
    //mainActivity = Robolectric.setupActivity(MainActivity.class);
}


@Test
public void testOnCreate() {
    when(restService.executeServerCall()).thenReturn(true);
    Robolectric.setupActivity(MainActivity.class);
}

@Test
public void testPresenter() {
    when(presenter.textShow()).thenReturn("MOCKING");
    Robolectric.setupActivity(MainActivity.class);
    MainActivity mainActivityVal = Robolectric.setupActivity(MainActivity.class);
    TextView results = (TextView) mainActivityVal.findViewById(R.id.text);
    Button button = (Button) mainActivityVal.findViewById(R.id.reload);
    mainActivityVal.presenter = presenter;
    button.performClick();
    Assert.assertEquals("MOCKING",mainActivityVal.presenter.textShow());
}

@fabioCollini
Copy link
Owner

Hi, using this work around it works but it's not the best way to do it.
I tried to implement the same test and it works, you can find it here: https://github.com/fabioCollini/DaggerMock/tree/master/RealWorldApp/src/test/java/it/cosenonjaviste/daggermock/realworldapp/robolectric

Looking at your example there is something strange, why are you invoking setupActivity twice?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants