Java单元测试 - 如何使用mockito答案对异步方法(使用回调)进行单元测试

时间:2014-08-02 21:17:46

标签: java unit-testing callback mockito

我在Logic逻辑

中有以下方法
public class Logic implements ILogic {

@Override
public void doSomethingInterestingAsync(final int number, 
                                        final ICallback callback){
    new Thread(new Runnable() {
        @Override
        public void run() {
            callback.response(number+1);
        }
    }).start();
  }
}

我通常使用

来调用它
ILogic.doSomethingInterestingAsync(1, new ICallback() {
    @Override
    public void response(int number) {
        System.out.println(String.format("response - %s", number));
    }
});

现在我想对它进行单元测试。

所以我认为一个解决方案是CountDownLatch(在other SO线程中找到)
如下:

@Test
public void testDoSomethingInterestingAsync_CountDownLatch() throws Exception {
    final CountDownLatch lock = new CountDownLatch(1);

    ILogic ILogic = new Logic();
    final int testNumber = 1;
    ILogic.doSomethingInterestingAsync(testNumber, new ICallback() {
        @Override
        public void response(int number) {
            assertEquals(testNumber + 1, number);
            lock.countDown();
        }
    });
    assertEquals(true, lock.await(10000, TimeUnit.MILLISECONDS));
}

效果很好。
但我也读过关于Mockito中的答案可能是更好的做法,
但我不能完全遵循这些例子 如何使用Mockito工具使用回调编写方法的单元测试?
谢谢。

2 个答案:

答案 0 :(得分:2)

我不明白为什么你需要CountDownLatch开始(根据你发布的代码来判断),所以我会在我的回答中跳过这个,随意添加一条评论来解释我的内容我失踪了。

我按如下方式测试:

@Test
public void testDoSomethingInterestingAsyncIncrementsParameter() {
    ILogic logic = new Logic();
    ICallback callback = mock(ICallback.class);

    logic.doSomethingInterestingAsync(SOME_NUMBER, callback);

    verify(callback, timeout(1000)).response(SOME_NUMBER + 1);
}

答案 1 :(得分:2)

CoundownLatch方法可以正常工作,但如果你的回调中的断言失败,测试仍然会成功。为什么?主测试线程不知道其他线程正在做什么 - 因此断言失败只有在主测试线程中出现时才会被注意到。

测试线程/异步代码的更好,更简单的方法是使用ConcurrentUnit之类的东西:

final Waiter waiter = new Waiter();

new Thread(() -> {
  doSomeWork();
  waiter.assertTrue(true);
  waiter.resume();
}).start();

// Wait for resume() to be called
waiter.await(1000);

无需使用CountdownLatch和断言通过Waiter工作完成,如你所料。