如何使 JUnit4 "Wait" 的异步作业在 运行 测试之前完成
How to make JUnit4 "Wait" for asynchronous job to finish before running tests
我正在尝试为与云服务通信的 android 应用程序编写测试。
理论上测试的流程应该是这样的:
- 在工作线程中向服务器发送请求
- 等待服务器响应
- 检查服务器返回的响应
我正在尝试使用 Espresso 的 IdlingResource
class 来完成此操作,但它没有按预期工作。这是我目前所拥有的
我的测试:
@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 的视图匹配器一起使用时,测试会正确执行,activity 等待然后检查结果。
然而,普通的 JUNIT4 断言方法被忽略,JUnit 不等待我的云操作完成。
有没有可能 IdlingResource
只适用于 Espresso 方法?还是我做错了什么?
我用 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()
方法中检查它。
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);
}
我正在尝试为与云服务通信的 android 应用程序编写测试。 理论上测试的流程应该是这样的:
- 在工作线程中向服务器发送请求
- 等待服务器响应
- 检查服务器返回的响应
我正在尝试使用 Espresso 的 IdlingResource
class 来完成此操作,但它没有按预期工作。这是我目前所拥有的
我的测试:
@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 的视图匹配器一起使用时,测试会正确执行,activity 等待然后检查结果。
然而,普通的 JUNIT4 断言方法被忽略,JUnit 不等待我的云操作完成。
有没有可能 IdlingResource
只适用于 Espresso 方法?还是我做错了什么?
我用 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()
方法中检查它。
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);
}