lundi 11 juillet 2016

Unit Testing MVP using mockito with callbacks

Android Studio 2.1.2

I am trying to test some callback events. I have demostrated in this simple app simulating a download.

I have added the code snippets for the model, presenter, view, and testPresenter.

My DownloadModel

public interface DownloadModelContract {
    void retrieveData();
}

public class DownloadModel implements DownloadModelContract {
    private DownloadPresenterContract.Events mPresenterEventsContract;

    public DownloadModel(DownloadPresenterContract.Events downloadPresenterContract) {
        mPresenterEventsContract = downloadPresenterContract;
    }

    @Override
    public void retrieveData() {
        boolean isDownloaded = true;

        /* SAMPLE Do something here to simulate a success or failure */

        /* IN A MOCKED IMPLEMENTATION THESE WOULD NEVER BE CALLED */
        if(isDownloaded) {
            mPresenterEventsContract.onDownloadSuccess();
        }
        else {
            mPresenterEventsContract.onDownloadFailed();
        }
}

My Presenter

public interface DownloadPresenterContract {
    interface Operations<DownloadViewContract> {
        void attachView(DownloadViewContract view);
        void detachView();
        void getData();
    }

    interface Events {
        void onDownloadSuccess();
        void onDownloadFailed();
    }
}

public class DownloadPresenterImp implements
        DownloadPresenterContract.Operations<DownloadViewContract>,
        DownloadPresenterContract.Events {

    private DownloadViewContract mView;
    private DownloadModelContract mDownloadModelContract;

    public DownloadPresenterImp(DownloadModelContract downloadModelContract) {
        mDownloadModelContract = downloadModelContract;
    }

    /* Operations */
    @Override
    public void attachView(DownloadViewContract view) {
        mView = view;
    }

    @Override
    public void detachView() {
        mView = null;
        mDownloadModelContract.unsubscribe();
    }

    @Override
    public void getData() {
        Timber.d("getData");
        mDownloadModelContract.retrieveData();
    }

    /* Events */
    @Override
    public void onDownloadSuccess() {
        Timber.d("onDownloadSuccess");
        mView.onSuccessDownload();
    }

    @Override
    public void onDownloadFailed() {
        Timber.e("onDownloadFailed");
        mView.onFailureDownload("Failed");
    }
}

Interface for the view

public interface DownloadViewContract {
    void onSuccessDownload();
    void onFailureDownload(String errMsg);
}

Now for the jvm unit testing

public class DownloadPresenterImpTest {
    private DownloadModelContract mockDownloadModelContract;
    private DownloadViewContract mockDownloadViewContract;
    private DownloadPresenterImp downloadPresenterImp;

    @Before
    public void setUp() throws Exception {
        mockDownloadModelContract = mock(DownloadModelContract.class);
        mockDownloadViewContract = mock(DownloadViewContract.class);
        downloadPresenterImp = new DownloadPresenterImp(mockDownloadModelContract);

        downloadPresenterImp.attachView(mockDownloadViewContract);
    }

    @Test
    public void shouldSuccessfullyDownloadData() throws Exception {
        downloadPresenterImp.getData();

        verify(mockDownloadViewContract, times(1)).onSuccessDownload();
        verify(mockDownloadViewContract, never()).onFailureDownload(anyString());
    }
}

The way it works when testing:

1) downloadPresenterImp.getData() will call the concrete implementation.
2) This will call mDownloadModelContract.retrieveData(); as this is a mock it will just return
3) In the DownloadModel retrieveData if download fails or succeeds the mocked function retrieveData will be called. so onSuccessDownload and onFailureDownload will never be called.

I would like to know how I can test in retrieveData that either mPresenterEventsContract.onSuccessDownload or mPresenterEventsContract.onFailureDownload was called.

Is there any way to test this implementation?

Many thanks for any suggestions,

Aucun commentaire:

Enregistrer un commentaire