锁定异步方法直到回调

时间:2014-07-11 09:59:34

标签: java android multithreading testing concurrency

我有一个测试方法

Service.signup(String username, String password, Callback listener);

我写了一个MockCallback来获得响应

class MockCallback implements Callback {
   String res;
   public void done(String res) {
      this.res = res;
      this.notifyAll()
   }
}

我为它编写了一个测试用例,我必须等待Service.signup完成,才能测试结果。

MockCallback cb = new MockCallback();
sychronized(cb) {
   cb.wait();
   service.signup("foo", "bar", cb);
}
assertEquals(cb.res, "hello");

但它不能按照我的预期运作,cb.resnull,它在assertEquals(cb.res, "hello")之后立即调用service.signup,而不是我想要的,我该如何解决?

2 个答案:

答案 0 :(得分:0)

使用CountDownLatch

class MockCallback implements Callback {
   private final CountDownLatch latch;
   String res;

   public MockCallback(CountDownLatch latch) { this.latch = latch; }

   public void done(String res) {
      this.res = res;
      latch.countDown();
   }
}

在你的测试用例中:

CountDownLatch latch = new CountDownLatch();
MockCallback cb = new MockCallback(latch);
service.signup("foo", "bar", cb);
latch.await(); // wait for latch to count down
assertEquals(cb.res, "hello");

答案 1 :(得分:0)

您没有正确使用等待/通知模式。


应使用与wait()

相同的监视器同步

A。 notifyAll()

B。生产者调用(= signup())不应位于同步块内

C。 wait()应该包含一个任务完成的测试循环,在你的情况下应该测试res!= null。

D。而且,让所有同步监视器成为最终的真的好主意


这样的事情:

class MockCallback implements Callback {
   String res;
   public synchronized void done(String res) { //<----------- now synchronized
      this.res = res;
      this.notifyAll()
   }
}

final MockCallback cb = new MockCallback(); //<----------- make monitor obj final


service.signup("foo", "bar", cb); //<----------- call not synchronized

sychronized(cb) {
   while (cr.res == null) { //<------------- wait in loop and check completion condition
      cb.wait();
   }
}
assertEquals(cb.res, "hello");