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

7

我正在尝试编写一个测试,用于与云服务通信的Android应用程序。

理论上,测试的流程应该是这样的:

  1. 在工作线程中向服务器发送请求
  2. 等待来自服务器的响应
  3. 检查服务器返回的响应

我正在尝试使用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();
}
}

The 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方法一起使用?还是我做错了什么?


从理论上讲,你可以发送请求 - 类似于 - 如果工作完成则发送 true 否则发送 false,并且你可以使用同步方法来保持工作,直到从服务器收到 true - Y.Kaan Yılmaz
2个回答

7

我使用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()方法中进行检查。

成功了!Awaitility就是我在寻找的那种库。非常感谢! - Charles-Eugene Loubao
对于现在看到这个的任何人来说,CountDownLatch 可能是更好的选择。 - nasch

7

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

Countdown latch是一个简单而优雅的解决方案,不需要外部库。它还可以帮助您专注于要测试的实际逻辑,而不是过度设计异步等待或等待响应。

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);

    }

对我来说,这似乎更加优雅,而且不需要额外的库。 - MFAL

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接