有时候,需要对一些异步方法进行单元测试(尽管不推荐这样做),传统的assert只能在调用线程抛出AssertException,而测试框架往往只能监测主线程上的AssertException(JUnit),所以需要在主线程上等待异步调用结束,再去assert结果。
利用Java8的CompletableFuture
public class AsyncTestHelper<T> {
private CompletableFuture<T> mFuture = new CompletableFuture<>();
public CompletableFuture<T> getFuture() {
return mFuture;
}
public void assertBlock(Callable<T> callable) {
try {
T result = callable.call();
complete(result);
} catch (Throwable e) {
completeExceptionally(e);
}
}
public void complete(T value) {
mFuture.complete(value);
}
public void completeExceptionally(Throwable throwable) {
mFuture.completeExceptionally(throwable);
}
public T waitForCompletion() throws Throwable {
return waitForCompletion(0);
}
public T waitForCompletion(int timeout) throws Throwable {
T result = null;
try {
if (timeout <= 0) {
result = mFuture.get();
} else {
result = mFuture.get(timeout
, TimeUnit.MILLISECONDS);
}
} catch (Throwable ex) {
if (ex instanceof ExecutionException) {
throw ex.getCause();
} else {
throw ex;
}
}
return result;
}
}
使用例子如下所示:
@Test
public void assertGetDeviceInfo() throws Throwable {
XLinkCoreDevice nullDevice = createTestDevice();
final AsyncTestHelper<XLinkCoreDeviceInfo> helper = new AsyncTestHelper<>();
XLinkCoreSDK.getInstance().getDeviceInfo(
nullDevice,
new XLinkCoreSDK.Callback<XLinkCoreDeviceInfo>() {
@Override
public void onSuccess(final XLinkCoreDeviceInfo result) {
println("onSuccess() called with: result = [" + result + "]");
// 异步回调
helper.assertBlock(new Callable<XLinkCoreDeviceInfo>() {
@Override
public XLinkCoreDeviceInfo call() throws Exception {
assertEquals(true, result.isBound());
assertEquals(5, result.getProtocolVersion());
assertArrayEquals(ByteUtil.hexToBytes(TEST_DEVICE_MAC), result.getMac());
assertEquals(TEST_DEVICE_PRODUCT_ID, result.getPid());
return result;
}
});
}
@Override
public void onFail(XLinkCoreException exception) {
println("onFail() called with: exception = [" + exception + "]");
helper.completeExceptionally(exception);
}
}
);
helper.waitForCompletion(); // 等待结果,并抛出原有的Exception
}
欢迎提出任何建议~