As I am trying to conduct the following simple Presenter Test
public class NewsPresenterTest {
private static List<News> NEWS_HEADLINES;
@Mock
private NewsRepository mNewsRepository;
@Mock
private Picasso mPicassoClient;
@Mock
private ChromeTabsWrapper mChromeTabsWrapper;
@Mock
private NewsContract.View mNewsView;
@Captor
private ArgumentCaptor<NewsDataSource.LoadNewsCallback> mLoadNewsCallbackCaptor;
private NewsPresenter mNewsPresenter;
@Before
public void setupNewsPresenter() {
// inject the mocks
MockitoAnnotations.initMocks(this);
mNewsPresenter = new NewsPresenter(mNewsRepository, new CompositeDisposable(), mPicassoClient, mChromeTabsWrapper);
mNewsPresenter.subscribe(mNewsView);
NEWS_HEADLINES = Lists.newArrayList(...);
}
@Test
public void loadHeadlinesNewsFromRepositoryAndLoadIntoView(){
// verify certain behavior
}
}
I seem to not be able in mocking mPicassoClient
, as result getting the following exception:
java.lang.ExceptionInInitializerError
at sun.reflect.GeneratedSerializationConstructorAccessor3.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
...more
Caused by: java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.os.Looper.getMainLooper(Looper.java)
at com.squareup.picasso.Picasso.<clinit>(Picasso.java:109)
... and more
As the stack states, the exception occurs when mocks are being initiated, to be more accurate on this line
MockitoAnnotations.initMocks(this);
Therefore mocking Picasso.class
fails. What am I doing wrong?
The Picasso class doesn't belong in your presenter. Move the call to Picasso inside your Fragment. Note that this doesn't prevent it from being covered by the test (in a less explicit way):
Previously:
newsRepository.getNews(date)
.subscribe(news ->
Picasso.loadImage(news.getImageUrl()))
Refactored:
newsRepository.getNews(date)
.subscribe(news ->
view.loadImage(news.getImageUrl()))
Where view
is the View from Model/View/Presenter and is implemented by your Activity or Fragment. Inside your Fragment or Activity:
@Override
public void loadImage(String url) {
Picasso.loadImage(url);
}