skip to content

Mockito offers both verify(mock, timeout(200)).send(msg) and verify(mock, after(200)).send(msg). How does each one spend those 200 milliseconds, and what can one catch that the other cannot?

level: middleimportance: must knowfreq 38%

answer

  1. timeout = up to; after = exactly
  2. return-on-success flag is the only difference
  3. after catches the extra 3rd call
  4. never()/atMost() belong to after
  5. big timeout free, big after expensive

basics

~20 s

timeout(200) polls and returns as soon as the verification passes, so it is an upper bound. after(200) always waits the whole 200 ms and only then asserts, so it can catch extra or late calls that timeout would have already passed over.

solid answer

~40 s

Both wrap a verification mode in a timed loop; they differ in when they stop. - timeout(200) is fail-fast on success: the first passing check returns. Best for 'this should eventually happen'. Cheap on the happy path, so make it generous. - after(200) waits the full window regardless, re-evaluating throughout, and reports the state at the end. Best for 'this should happen exactly n times and no more' or 'this should not happen at all'. It costs 200 ms on every run, pass or fail, so keep it small and rare. The practical consequence: verify(mock, timeout(200).times(2)) returns the moment the second call lands and will happily miss a third arriving at 150 ms; verify(mock, after(200).times(2)) fails on that third call. Negative and at-most expectations therefore belong to after(), never to timeout().

code

java · 8 lines
java
// eventual: returns as soon as the 2nd call lands, a 3rd would go unnoticed
verify(publisher, timeout(2000).times(2)).publish(any());

// settled: always waits 200 ms, fails if a 3rd call arrives inside the window
verify(publisher, after(200).times(2)).publish(any());

// absence: only after() may express a negative expectation
verify(publisher, after(200).never()).publish(any());

go deeper

for a junior

Remember the one-liner: timeout waits at most that long, after waits exactly that long, and negative checks need after.

for a middle

Explain the shared polling loop and the return-on-success difference, and give the concrete example of the third call that timeout misses and after catches.

for a senior

Talk about the cost asymmetry driving the style rule (generous timeouts, short afters) and the fundamental weakness of absence-by-waiting.

for a principal

Position both as last resorts: prefer deterministic completion signals; budget the aggregate wall clock afters add across a suite and set a team norm for when they are allowed.

## Same machinery, opposite stopping rule Mockito implements both with one timed-verification decorator: a loop that repeatedly runs the wrapped mode (times(1) by default) against the mock's recorded invocations, with a short polling interval. The only difference is a flag for whether success ends the loop. timeout(ms) sets return-on-success: the first time the wrapped check passes, verification is over. The remaining budget is never spent. Failures are retried until the clock runs out, then the last error is rethrown. after(ms) does not return on success. It keeps re-checking for the whole window; a success is provisional and can be invalidated by a later invocation, and the verdict is whatever holds when the window closes. That is why after() is described as full-wait semantics. ## What each can prove timeout answers 'does this eventually happen (at least in this shape)?'. Because it stops at the first pass, it cannot prove the absence of later interactions. verify(mock, timeout(500).times(2)).send(any()) succeeds the instant the second send is recorded; a third send at 300 ms is invisible to it. after answers 'what is true after the system has been given this long to settle?'. Since it evaluates at the end, it catches over-invocation, and it is the only correct home for negative expectations: after(200).never().send(any()) means 'give it 200 ms and confirm nothing was sent'. after(200).atMost(3) likewise bounds a rate. ## Cost model, and why it drives style Because timeout is fail-fast on success, its number is a pure upper bound: a 5 s timeout in a suite where the work takes 20 ms adds 20 ms. Generous timeouts are therefore the flake-resistant choice. after is the opposite: every run pays the wall clock, so a 2 s after in a hundred tests is over three minutes of dead time. Keep after windows short (tens to a couple of hundred milliseconds) and use them sparingly. ## Negative assertions are inherently weak Even after(200).never() only proves nothing happened within 200 ms. Absence over any window is unprovable by waiting; you are trading test time for confidence. Where possible, replace it with a positive, deterministic signal: complete the pipeline, then assert with verifyNoInteractions or by checking that some terminal state was reached without the side effect. ## A rule of thumb Positive, eventual expectations get timeout with a generous budget. Exact-count or negative expectations under concurrency get after with a small budget, and ideally get replaced by a deterministic barrier. Mixing them up produces the two classic failures: flaky tests from too-tight timeouts, and slow suites from too-long afters.

  • Why is it fine to set timeout(5000) but reckless to set after(5000)?
    timeout returns on the first successful check, so a long budget is only consumed by tests that are going to fail anyway. after always burns its full window on every run, pass or fail, so a five-second after multiplies directly into suite runtime. Long timeouts buy stability for free; long afters buy it with wall-clock time.
  • How would you assert that exactly one message is sent even though the sender is asynchronous, without a fixed wait?
    Make the completion observable: have the test await a CountDownLatch counted down from the mock's answer or from a completion callback, then assert with verify(mock).send(msg) and verifyNoMoreInteractions(mock). That converts a timing guess into a happens-before edge; after(ms).times(1) is the fallback when no such signal exists.

timeout is waiting at the door and leaving the moment your friend arrives; after is standing there the full ten minutes to see whether anyone else shows up too.

saying these in an interview costs you the question

  • Believing timeout also waits the full duration, making the two interchangeable
  • Using timeout with never() or atMost() instead of after()
  • Claiming after() cannot fail before its window ends
  • Using long after() windows everywhere and then complaining the suite is slow
  • Treating after(ms).never() as proof that something can never happen at all

context