Mockito:轮询等待验证

时间:2019-06-24 22:25:30

标签: java mockito

@Mock WorkItem;

@Test(timeOut = 300000)
public void testSomething() throws Exception {
    <do some testing>

    verifyWorkDone()
}

public void verifyWorkDone() {
    ArgumentCaptor<WorkItemQuery> captor = 
    ArgumentCaptor.forClass(WorkItemQuery.class);
    verify(WorkItem, atLeastOnce()).call(captor.capture());
}

我想为verifyWorkDone()更改上面的代码块,以便它继续重试验证,直到测试超时。

有没有很好的方法来实现这一目标?只是抛出一会儿循环?

1 个答案:

答案 0 :(得分:1)

测试异步行为通常不应该涉及轮询以检查是否已将某些事情作为测试行为的一部分进行了检查。我建议隔离将异步运行的组件并“正常”对其进行单独测试。然后,通过在响应之前将异步组件模拟到wait一段固定的时间,来测试将在异步组件上等待的组件。您可以使用它来测试所有相关情况下的等待组件:响应如期出现,响应来了,但这是一个错误,响应永远不会在超时之前出现等。

例如

public interface AsyncObject {
    public void invoke();
    public Object check();
}

public class MyMockAsyncObject implements AsyncObject {

    private long delay;
    private long startTimeMillis;

    public MyMockAsyncObject(long delay) {
        this.delay = delay;
    }

    public void invoke() {
        startTimeMillis = now();
    }

    public Object check() {
        if (now() - startTimeMillis > delay) {
            return new Object();
        } else {
            return null;
        }
    }
}

public class Waiter {

    public AsyncObject myAsyncObject;

    public Waiter(AsyncObject async) {
        this.myAsyncObject = async;
    }

    public Object getResult() {
        myAsyncObject.invoke();
        return this.waitForResult();
    }

    private Object waitForResult() {
        while(// is not timed out) {
            // wait a while
            myAsyncObject.check(); 
            // return result if it's there
        }
        throw new Exception();
    }
}