android - 如何正确地将 Picasso 模拟到单元测试中?

标签 android testing mocking mockito picasso

因为我正在尝试进行以下简单的 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 失败。我做错了什么?

最佳答案

Picasso 类不属于您的演示者。将调用移至 Fragment 中的 Picasso。请注意,这不会阻止它被测试覆盖(以不太明确的方式):

之前:

newsRepository.getNews(date) 
   .subscribe(news ->
      Picasso.loadImage(news.getImageUrl()))

重构:

newsRepository.getNews(date)
    .subscribe(news ->
        view.loadImage(news.getImageUrl()))

view 是来自 Model/View/Presenter 的 View ,由您的 Activity 或 Fragment 实现。在您的 fragment 或 Activity 中:

@Override
public void loadImage(String url) {
    Picasso.loadImage(url);
}

关于android - 如何正确地将 Picasso 模拟到单元测试中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51138335/

相关文章:

android - 如何在 Android WebView 中包含 BACK 键

android - 使用新适配器更新 recyclerview

testing - 在grails的集成测试中测试beforeInterceptor

sql-server - 用于网站/Web 应用程序负载测试的工具?

node.js - 如何创建模拟 http.ServerRequest 和 http.ServerResponse?

ruby - 我如何模拟或覆盖 Kernel.system?

java - jUnit 在测试中跳过注入(inject)模拟方法中的方法调用

android - 如何在另一个类中委托(delegate)一个字符串而不重新定义它?

c# - 将系统类作为构造函数参数传递

java - 如何在 Libgdx Java 中实现缩放和平移?