【问题标题】:Testing asynchronous code with JUnit使用 JUnit 测试异步代码
【发布时间】:2012-01-18 00:29:47
【问题描述】:
我想测试一些依赖网络传输的代码。代码发出请求并提供回调 - 当请求完成时,回调被触发。我想模拟出网络传输,并使用Thread.sleep 来模拟一些延迟......但这当然会使整个测试暂停。
到目前为止,我一直在创建新线程并在整个测试过程中使用CountDownLatches 来阻止测试在触发回调之前结束。我的模拟网络对象创建了一个新线程,在该线程上休眠,然后触发回调。这实际上工作得很好,但问题是回调中的任何断言错误都不会报告给原始的 junit 线程 - 相反,我在控制台上收到异常文本,它更难理解和使用。
我希望有一个:
- 一种将
assertEquals 输出从衍生线程传送到主JUnit 输出收集器的方法,或者
- 在 JUnit 中测试线程代码的完全不同且更好的方法,或
- 在单线程中模拟异步代码的某种方式
感谢您的任何想法!
【问题讨论】:
标签:
java
multithreading
testing
junit
【解决方案1】:
当我不得不实现类似于你的异步机制时,我创建了抽象类AsyncTestCase,它包含测试错误并提供特殊方法waitForCallback()。当异步任务在预期结果中发现错误时,它会将错误放入此变量中。 setter 对waitForCallback() 使用的对象调用notify()。因此,当回调到达时,它会立即导致测试唤醒。然后我可以调用所有断言,包括由异步任务存储的断言。
并且不要忘记在测试中设置超时以防止它们永远休眠:
@Test(timeout=10000)
public void mytest() {
callAsyncTask();
waitForAsyncTask(); // from base class
assertAsyncTaskResult(); // from base class
}
【解决方案2】:
您所描述的是ConcurrentUnit。这是一个例子:
final Waiter waiter = new Waiter();
new Thread(() -> {
doSomeWork();
waiter.assertTrue(true);
waiter.resume();
}).start();
// Wait for resume() to be called
waiter.await(1000);