Moxy icon indicating copy to clipboard operation
Moxy copied to clipboard

Mocking the presenter

Open Macarse opened this issue 7 years ago • 6 comments

Hello

I am trying to create a simple espresso UI test. My Activity has a:

@Override
public void updateResults(List<Model> modelList) {
  adapter.update(modelList);
}

The presenter fetches the data on attachView() and calls the activity/view doing:

getViewState().updateResults(modelList);

My espresso test looks like this:

@Test
public void myTest() {
  Intent intent = new Intent();
  intent.putExtra("xxx", "xxx");
  activityRule.launchActivity(intent);
  activityRule.getActivity().updateResults(createMockedList());

  onView(withId(R.id.recycler_view))
  // rest of the espresso code
}

Since I just want to test the UI, I would like to mock the presenter. If I leave the presenter as it is, attachView() will be called and I don't want that.

I tried forcing the presenter using:

MvpFacade.getInstance().getPresenterStore().add("TravelerMessagesTestPresenter", new MockedMvpPresenter());

from ActivityTestRule:beforeActivityLaunched() but you are reading the tag from the bundle and I can't modify that, just the intent.

Any idea on how to do it? If there is no way of doing this, would it be ok to add a "read tag from intent" in Moxy's MvpDelegate to contemplate this use case?

Thanks!

Macarse avatar Nov 17 '17 01:11 Macarse

Hi,

Do you want to mock Presenter? You able to do something like this:

MvpFacade.getInstance().presenterStore = object : PresenterStore() {
	override fun get(tag: String?): MvpPresenter<*> {
		return yourMockPresenter
	}
}

I have no other ideas =( I'll think yet

senneco avatar Nov 17 '17 04:11 senneco

Ok, I got it working.

Code looks like this:

private MockedPresenterStore mockedPresenterStore;
private PresenterStore originalPresenterStore;

@Rule
public ActivityTestRule<MyActivity> activityRule =
  new ActivityTestRule<MyActivity>(MyActivity.class, false, false) {

    @Override
    protected void beforeActivityLaunched() {
        super.beforeActivityLaunched();

        originalPresenterStore = MvpFacade.getInstance().getPresenterStore();
        mockedPresenterStore = new MockedPresenterStore(new MockedMvpPresenter());
        MvpFacade.getInstance().setPresenterStore(mockedPresenterStore);
    }

    @Override
    protected void afterActivityLaunched() {
        super.afterActivityLaunched();

        MvpFacade.getInstance().setPresenterStore(originalPresenterStore);
    }
};

static class MockedPresenterStore extends PresenterStore {

    private final MvpPresenter mockedMvpPresenter;

    public MockedPresenterStore(MvpPresenter mockedMvpPresenter) {
        this.mockedMvpPresenter = mockedMvpPresenter;
    }

    @Override
    public MvpPresenter get(String tag) {
        return mockedMvpPresenter;
    }
}

// Presenter mock.
static class MockedMvpPresenter extends TravelerMessagesPresenter {

    @Override
    protected void onFirstViewAttach() {
        // Do nothing
    }
}

@Test
public void testMessagesShownInList() throws Throwable {
    Intent intent = new Intent();
    intent.putExtra("xx", "xx");
    activityRule.launchActivity(intent);
    activityRule.runOnUiThread(() -> activityRule.getActivity().updateResults(getMockedList()));


    // espresso stuff here.
}

While this works, I don't like replacing the PresenterStore to be able to mock.

Are you against the idea of having a special tag stored in the intent and MvpDelegate reading from there just for testing purposes?

Macarse avatar Nov 17 '17 17:11 Macarse

@senneco ping?

Macarse avatar Nov 20 '17 22:11 Macarse

Hi @Macarse

I have some experimental code that allows you to specify tag's generator, but at the moment it's in development (because it's touch all moxy) :worried: I'll think about provides method wich will say presenter tag

senneco avatar Nov 21 '17 04:11 senneco

@senneco Nice. Did you push a branch?

Macarse avatar Nov 21 '17 10:11 Macarse

@Macarse no, it's only local experiments, because it's not ready absolutely =)

senneco avatar Nov 22 '17 06:11 senneco