2017-05-10 23 views
9

我试图用AndroidJunit4测试RecyclerView返回0,这是我的测试代码:的Android RecyclerView适配器个计数单元测试

@Rule 
    public ActivityTestRule<ProductListActivity> rule = new ActivityTestRule<>(ProductListActivity.class); 

............................ 
.......................... 

@Test 
    public void ensureDataIsLoadingOnSuccess() throws Exception { 
     ProductListActivity activity = rule.getActivity(); 
     ........................... 
     ............ 

     activity.runOnUiThread(new Runnable() { 
     public void run() { 
      activity.displayProducts(asList(product1, product2), 0); 
     } 
    }); 

     assertEquals(2, mAdapter.getItemCount()); 
     assertThat(((ProductAdapter) mAdapter).getItemAtPosition(0),sameInstance(product1)); 
     assertThat(((ProductAdapter) mAdapter).getItemAtPosition(1),sameInstance(product2)); 


    } 

这是在练习我的displayProducts代码():

@Override 
    public void displayProducts(List<Product> products, Integer pageNo) { 
     progressBar.setVisibility(View.GONE); 
     if (pageNo == 0 && products.size() == 0) { 
      noProductTextView.setVisibility(View.VISIBLE); 
     } else { 
      mProductAdapter.addProduct(products); 
      noProductTextView.setVisibility(View.GONE); 
      productListView.setVisibility(View.VISIBLE); 
     } 
    } 

这是给错误,如:

junit.framework.AssertionFailedError: expected:<2> but was:<0> 
at junit.framework.Assert.fail(Assert.java:50) 
at junit.framework.Assert.failNotEquals(Assert.java:287) 
at junit.framework.Assert.assertEquals(Assert.java:67) 
at junit.framework.Assert.assertEquals(Assert.java:199) 
at junit.framework.Assert.assertEquals(Assert.java:205) 
at com.kaushik.myredmart.ui.ProductListActivityTest.ensureDataIsLoadingOnSuccess(ProductListActivityTest.java:94) 

请帮助什么是我的代码的问题?

+0

你如何设置'mAdapter'? – tynn

+1

动画是您在ui测试中的敌人,每个progres栏,自定义动画或任何正在非异步线程池上完成的工作都不会使用espresso进行注册,并且只会运行其他断言,因为它认为没有什么可以等待。也尝试编写你的测试,你注入并设置数据的设置和拆卸,然后你的活动将在积累期间。您是否在displayProducts()后调用notifydataset? – originx

+0

mAdapter从哪里来?我认为你正在检查错误的适配器 – Tudor

回答

-1

我在这里可以看到一个问题,在Main/UI线程能够更新它之前,您正在查询列表大小。所以,你将不得不在当前线程中等待Activity完成更新主线程列表。

你可以做,

Thread.sleep(500); 
在测试类等

,以测试在活动列表中设置的行为,你会发现断言是有效的。

由于主线程运行无限,直到应用程序运行,您将不得不实现由Activity提供的回调接口,以通知填充列表何时完成。

+0

问题是为什么Espresso不会等到'MessageQueue'为空? – azizbekian

+0

@azizbekian,因为它在另一个线程(背景)上运行。 添加一个观察者设计模式,并将其捕获到确切的时间,否则使用线程休眠方法。 –

+0

您的说明不正确:Espresso在后台线程上运行**,但是**它将UI线程的MessageQueue侦听为空,并且只有在Espresso将继续使用匹配器时它才为空。您提出了一个解决方法,但不能说明问题出现的原因。 – azizbekian

0

原因是您的Espresso测试没有等待您的加载任务,这是非常耗时的。 您需要使用espresso-idling-resource来指示它等待此任务完成。

然后,您需要一个类来实现IdlingResource并将其声明为您的活动。

当您的Espresso测试运行时,它会知道并等待您长时间消耗的任务来完成并测试结果。

首先,添加它的依赖关系。其次,你需要在src/main/java/your-package文件夹中有两个Java文件。
SimpleCountingIdlingResource.java

public final class SimpleCountingIdlingResource implements IdlingResource { 

    private final String mResourceName; 

    private final AtomicInteger counter = new AtomicInteger(0); 

    // written from main thread, read from any thread. 
    private volatile ResourceCallback resourceCallback; 

    /** 
    * Creates a SimpleCountingIdlingResource 
    * 
    * @param resourceName the resource name this resource should report to Espresso. 
    */ 
    public SimpleCountingIdlingResource(String resourceName) { 
    mResourceName = checkNotNull(resourceName); 
    } 

    @Override public String getName() { 
    return mResourceName; 
    } 

    @Override public boolean isIdleNow() { 
    return counter.get() == 0; 
    } 

    @Override public void registerIdleTransitionCallback(ResourceCallback resourceCallback) { 
    this.resourceCallback = resourceCallback; 
    } 

    /** 
    * Increments the count of in-flight transactions to the resource being monitored. 
    */ 
    public void increment() { 
    counter.getAndIncrement(); 
    } 

    /** 
    * Decrements the count of in-flight transactions to the resource being monitored. 
    * 
    * If this operation results in the counter falling below 0 - an exception is raised. 
    * 
    * @throws IllegalStateException if the counter is below 0. 
    */ 
    public void decrement() { 
    int counterVal = counter.decrementAndGet(); 
    if (counterVal == 0) { 
     // we've gone from non-zero to zero. That means we're idle now! Tell espresso. 
     if (null != resourceCallback) { 
     resourceCallback.onTransitionToIdle(); 
     } 
    } 

    if (counterVal < 0) { 
     throw new IllegalArgumentException("Counter has been corrupted!"); 
    } 
    } 
} 

EspressoIdlingResource.java

public class EspressoIdlingResource { 

    private static final String RESOURCE = "GLOBAL"; 

    private static SimpleCountingIdlingResource mCountingIdlingResource = 
     new SimpleCountingIdlingResource(RESOURCE); 

    public static void increment() { 
    mCountingIdlingResource.increment(); 
    } 

    public static void decrement() { 
    mCountingIdlingResource.decrement(); 
    } 

    public static IdlingResource getIdlingResource() { 
    return mCountingIdlingResource; 
    } 
} 

确定。让我们转到活动,您需要耗费大量时间。首先,把这个方法放在底部。

@VisibleForTesting 
    public IdlingResource getCountingIdlingResource() { 
     return EspressoIdlingResource.getIdlingResource(); 
    } 

在你耗时的任务中。你应该告诉你的浓咖啡要这样等。

EspressoIdlingResource.increment(); 

    yourTask.run(new Callback() { 
    void onFinish(){ 
     EspressoIdlingResource.decrement(); 
    } 
    }) 

最后一步是在你的UI测试类中定义这些方法。

@Before 
public void registerIdlingResource() { 
    Espresso.registerIdlingResources(mOnBoardActivityTestRule.getActivity().getCountingIdlingResource()); 
} 

/** 
* Unregisters your idling resource so it can be garbage collected and does not leak any memory 
*/ 
@After 
public void unregisterIdlingResource() { 
    Espresso.unregisterIdlingResources(mOnBoardActivityTestRule.getActivity().getCountingIdlingResource()); 
} 

是的。最后我们完成了。

相关问题