简体   繁体   中英

Verify alternating calls in Mockito

I am working on a unit test for a class that uses the Java 7 WatchService class features. The WatchService class provides a take() function that returns a WatchKey object the next time there is a change in the directory. The WatchKey has to be reset before the next time take() is called on the WatchService.

Mockito provides an InOrder class to help with this sort of thing, but it doesn't seem to play well with repeated alternation.

My best attempt...

for(int i = 1; i < 4; i++){
    inOrder.verify(mockWatcher, atLeast(i)).take();
    inOrder.verify(mockKey, atLeast(i)).reset();
}
inOrder.verify(mockWatcher, times(4)).take(); // the last take() is interrupted before returning

fails with the error

org.mockito.exceptions.verification.VerificationInOrderFailure: 
Verification in order failure
Wanted but not invoked:
watchKey.reset();
-> at com.co3.examples.Co3DirectoryWatcherTest.run_noProblems_performActionsCorrectly(Co3DirectoryWatcherTest.java:273)
Wanted anywhere AFTER following interaction:
watchService.take();
-> at com.co3.examples.Co3DirectoryWatcher.run(Co3DirectoryWatcher.java:78)

    at com.co3.examples.Co3DirectoryWatcherTest.run_noProblems_performActionsCorrectly(Co3DirectoryWatcherTest.java:273)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

What is the canonical way to verify this behavior?

You might try making your "when" clauses for these methods a little more complicated, by using an "Answer" callback. In that Answer callback, you can utilize a shared data structure that records the ordering of calls. After the execution of the CUT is complete, you can then analyze the recorded data for correctness.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM