如何在运行测试之前使JUnit4“等待”异步作业完成

时间:2016-05-08 19:27:09

标签: java android multithreading junit4 android-espresso

我正在尝试为我的Android应用程序编写测试,该测试与云服务进行通信。 从理论上讲,测试的流程应该是这样的:

  1. 在工作线程中向服务器发送请求
  2. 等待来自服务器的响应
  3. 检查服务器返回的响应
  4. 我正在尝试使用Espresso的IdlingResource类来实现这一目标,但它没有按预期工作。这是我到目前为止所拥有的

    我的测试:

    @RunWith(AndroidJUnit4.class)
    public class CloudManagerTest {
    
    FirebaseOperationIdlingResource mIdlingResource;
    
    @Before
    public void setup() {
        mIdlingResource = new FirebaseOperationIdlingResource();
        Espresso.registerIdlingResources(mIdlingResource);
    }
    
    @Test
    public void testAsyncOperation() {
        Cloud.CLOUD_MANAGER.getDatabase().getCategories(new OperationResult<List<Category>>() {
            @Override
            public void onResult(boolean success, List<Category> result) {
                mIdlingResource.onOperationEnded();
                assertTrue(success);
                assertNotNull(result);
            }
        });
        mIdlingResource.onOperationStarted();
    }
    }
    

    FirebaseOperationIdlingResource

    public class FirebaseOperationIdlingResource implements IdlingResource {
    
    private boolean idleNow = true;
    private ResourceCallback callback;
    
    
    @Override
    public String getName() {
        return String.valueOf(System.currentTimeMillis());
    }
    
    public void onOperationStarted() {
        idleNow = false;
    }
    
    public void onOperationEnded() {
        idleNow = true;
        if (callback != null) {
            callback.onTransitionToIdle();
        }
    }
    
    @Override
    public boolean isIdleNow() {
        synchronized (this) {
            return idleNow;
        }
    }
    
    @Override
    public void registerIdleTransitionCallback(ResourceCallback callback) {
        this.callback = callback;
    }}
    

    当与Espresso的视图匹配使用时,测试会正确执行,活动会等待,然后检查结果。

    然而,忽略了普通的JUNIT4断言方法,JUnit没有等待我的云操作完成。

    IdlingResource只能使用Espresso方法吗?或者我做错了什么?

2 个答案:

答案 0 :(得分:6)

我使用Awaitility之类的东西。

它有一个非常好的指南,这是基本的想法:

您需要等待的地方:

await().until(newUserIsAdded());

别处:

private Callable<Boolean> newUserIsAdded() {
      return new Callable<Boolean>() {
            public Boolean call() throws Exception {
                  return userRepository.size() == 1; // The condition that must be fulfilled
            }
      };
}

我认为此示例与您正在执行的操作非常相似,因此请将异步操作的结果保存到字段中,并使用call()方法进行检查。

答案 1 :(得分:1)

Junit不会等待异步任务完成。您可以使用CountDownLatch阻止线程,直到收到来自服务器或超时的响应。

void testBackgroundJob() {

        Latch latch = new CountDownLatch(1);

        //Do your async job
        Service.doSomething(new Callback() {

            @Override
            public void onResponse(){
                ACTUAL_RESULT = SUCCESS;
                latch.countDown(); // notify the count down latch
                // assertEquals(..
            }

        });

        //Wait for api response async
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        assertEquals(expectedResult, ACTUAL_RESULT);

    }