代码之家  ›  专栏  ›  技术社区  ›  Catalin Ghita

如何正确地将毕加索模拟成单元测试?

  •  2
  • Catalin Ghita  · 技术社区  · 6 年前

    当我试图进行以下简单的演示者测试时

    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 失败。我做错什么了?

    1 回复  |  直到 6 年前
        1
  •  1
  •   David Rawson B Aristide    6 年前

    毕加索类不属于演示者。把对毕加索的召唤转移到你的片段里。注意,这并不能阻止它被测试覆盖(以一种不太明确的方式):

    以前:

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

    重构:

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

    在哪里? view 是来自模型/视图/演示者的视图,由活动或片段实现。在你的片段或活动中:

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