如何正确地将 Picasso 模拟到单元测试中?
How to properly mock Picasso into Unit Tests?
因为我正在尝试进行以下简单的 Presenter 测试
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
}
}
我似乎无法模拟 mPicassoClient
,结果出现以下异常:
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
作为堆栈状态,在启动模拟时发生异常,在这一行上更准确
MockitoAnnotations.initMocks(this);
因此模拟 Picasso.class
失败。我做错了什么?
毕加索 class 不属于您的演示者。将调用移至 Fragment 中的 Picasso。请注意,这不会阻止它被测试覆盖(以不太明确的方式):
之前:
newsRepository.getNews(date)
.subscribe(news ->
Picasso.loadImage(news.getImageUrl()))
重构:
newsRepository.getNews(date)
.subscribe(news ->
view.loadImage(news.getImageUrl()))
其中 view
是来自 Model/View/Presenter 的视图,由您的 Activity 或 Fragment 实现。在你的片段或 Activity:
@Override
public void loadImage(String url) {
Picasso.loadImage(url);
}
因为我正在尝试进行以下简单的 Presenter 测试
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
}
}
我似乎无法模拟 mPicassoClient
,结果出现以下异常:
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
作为堆栈状态,在启动模拟时发生异常,在这一行上更准确
MockitoAnnotations.initMocks(this);
因此模拟 Picasso.class
失败。我做错了什么?
毕加索 class 不属于您的演示者。将调用移至 Fragment 中的 Picasso。请注意,这不会阻止它被测试覆盖(以不太明确的方式):
之前:
newsRepository.getNews(date)
.subscribe(news ->
Picasso.loadImage(news.getImageUrl()))
重构:
newsRepository.getNews(date)
.subscribe(news ->
view.loadImage(news.getImageUrl()))
其中 view
是来自 Model/View/Presenter 的视图,由您的 Activity 或 Fragment 实现。在你的片段或 Activity:
@Override
public void loadImage(String url) {
Picasso.loadImage(url);
}