diff --git a/src/main/java/org/mockito/Mockito.java b/src/main/java/org/mockito/Mockito.java index af1ceb22e9..aea283881e 100644 --- a/src/main/java/org/mockito/Mockito.java +++ b/src/main/java/org/mockito/Mockito.java @@ -4,6 +4,8 @@ */ package org.mockito; +import java.time.Duration; + import org.mockito.exceptions.misusing.PotentialStubbingProblem; import org.mockito.exceptions.misusing.UnnecessaryStubbingException; import org.mockito.internal.InternalMockHandler; @@ -886,15 +888,15 @@ *

  *   //passes when someMethod() is called no later than within 100 ms
  *   //exits immediately when verification is satisfied (e.g. may not wait full 100 ms)
- *   verify(mock, timeout(100)).someMethod();
+ *   verify(mock, timeout(Duration.ofMillis(100))).someMethod();
  *   //above is an alias to:
- *   verify(mock, timeout(100).times(1)).someMethod();
+ *   verify(mock, timeout(Duration.ofMillis(100)).times(1)).someMethod();
  *
  *   //passes as soon as someMethod() has been called 2 times under 100 ms
- *   verify(mock, timeout(100).times(2)).someMethod();
+ *   verify(mock, timeout(Duration.ofMillis(100)).times(2)).someMethod();
  *
  *   //equivalent: this also passes as soon as someMethod() has been called 2 times under 100 ms
- *   verify(mock, timeout(100).atLeast(2)).someMethod();
+ *   verify(mock, timeout(Duration.ofMillis(100)).atLeast(2)).someMethod();
  * 
* * @@ -2846,10 +2848,45 @@ public static VerificationMode only() { * @param millis - duration in milliseconds * * @return object that allows fluent specification of the verification (times(x), atLeast(y), etc.) + * @deprecated Use {@link #timeout(Duration)} instead. */ @CheckReturnValue + @Deprecated public static VerificationWithTimeout timeout(long millis) { - return new Timeout(millis, VerificationModeFactory.times(1)); + return timeout(Duration.ofMillis(millis)); + } + + /** + * Verification will be triggered over and over until the given amount of time, allowing testing of async code. + * Useful when interactions with the mock object did not happened yet. + * Extensive use of {@code timeout()} method can be a code smell - there are better ways of testing concurrent code. + *

+ * See also {@link #after(Duration)} method for testing async code. + * Differences between {@code timeout()} and {@code after} are explained in Javadoc for {@link #after(Duration)}. + * + *


+     *   //passes when someMethod() is called no later than within 100 ms
+     *   //exits immediately when verification is satisfied (e.g. may not wait full 100 ms)
+     *   verify(mock, timeout(Duration.ofMillis(100))).someMethod();
+     *   //above is an alias to:
+     *   verify(mock, timeout(Duration.ofMillis(100)).times(1)).someMethod();
+     *
+     *   //passes as soon as someMethod() has been called 2 times under 100 ms
+     *   verify(mock, timeout(Duration.ofMillis(100)).times(2)).someMethod();
+     *
+     *   //equivalent: this also passes as soon as someMethod() has been called 2 times under 100 ms
+     *   verify(mock, timeout(Duration.ofMillis(100)).atLeast(2)).someMethod();
+     * 
+ * + * See examples in javadoc for {@link Mockito} class + * + * @param timeout how long to wait before timing out + * + * @return object that allows fluent specification of the verification (times(x), atLeast(y), etc.) + */ + @CheckReturnValue + public static VerificationWithTimeout timeout(Duration timeout) { + return new Timeout(timeout, VerificationModeFactory.times(1)); } /** @@ -2889,7 +2926,7 @@ public static VerificationWithTimeout timeout(long millis) { * //1. * mock.foo(); * verify(mock, after(1000)).foo(); - * //waits 1000 millis and succeeds + * //waits 1 second and succeeds * * //2. * mock.foo(); @@ -2902,10 +2939,68 @@ public static VerificationWithTimeout timeout(long millis) { * @param millis - duration in milliseconds * * @return object that allows fluent specification of the verification + * @deprecated Use {@link #after(Duration)} instead. */ @CheckReturnValue + @Deprecated public static VerificationAfterDelay after(long millis) { - return new After(millis, VerificationModeFactory.times(1)); + return after(Duration.ofMillis(millis)); + } + + /** + * Verification will be triggered after given amount of time, allowing testing of async code. + * Useful when interactions with the mock object did not happened yet. + * Extensive use of {@code after()} method can be a code smell - there are better ways of testing concurrent code. + *

+ * Not yet implemented to work with InOrder verification. + *

+ * See also {@link #timeout(Duration)} method for testing async code. + * Differences between {@code timeout()} and {@code after()} are explained below. + * + *


+     *   //passes after 100ms, if someMethod() has only been called once at that time.
+     *   verify(mock, after(Duration.ofMillis(100))).someMethod();
+     *   //above is an alias to:
+     *   verify(mock, after(Duration.ofMillis(100)).times(1)).someMethod();
+     *
+     *   //passes if someMethod() is called *exactly* 2 times, as tested after 100 millis
+     *   verify(mock, after(Duration.ofMillis(100)).times(2)).someMethod();
+     *
+     *   //passes if someMethod() has not been called, as tested after 100 millis
+     *   verify(mock, after(Duration.ofMillis(100)).never()).someMethod();
+     *
+     *   //verifies someMethod() after a given time span using given verification mode
+     *   //useful only if you have your own custom verification modes.
+     *   verify(mock, new After(Duration.ofMillis(100), yourOwnVerificationMode)).someMethod();
+     * 
+ * + * timeout() vs. after() + * + * Examples: + *

+     *   //1.
+     *   mock.foo();
+     *   verify(mock, after(Duration.ofSeconds(1))).foo();
+     *   //waits 1 second and succeeds
+     *
+     *   //2.
+     *   mock.foo();
+     *   verify(mock, timeout(Duration.ofSeconds(1))).foo();
+     *   //succeeds immediately
+     * 
+ * + * See examples in javadoc for {@link Mockito} class + * + * @param delay how to to wait before triggering verification + * + * @return object that allows fluent specification of the verification + */ + @CheckReturnValue + public static VerificationAfterDelay after(Duration delay) { + return new After(delay, VerificationModeFactory.times(1)); } /** diff --git a/src/main/java/org/mockito/internal/exceptions/Reporter.java b/src/main/java/org/mockito/internal/exceptions/Reporter.java index f661b81e5c..db8bbbeacc 100644 --- a/src/main/java/org/mockito/internal/exceptions/Reporter.java +++ b/src/main/java/org/mockito/internal/exceptions/Reporter.java @@ -10,6 +10,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -863,12 +864,12 @@ public static MockitoException usingConstructorWithFancySerializable(Serializabl return new MockitoException("Mocks instantiated with constructor cannot be combined with " + mode + " serialization mode."); } - public static MockitoException cannotCreateTimerWithNegativeDurationTime(long durationMillis) { + public static MockitoException cannotCreateTimerWithNegativeDurationTime(Duration duration) { return new FriendlyReminderException(join( "", "Don't panic! I'm just a friendly reminder!", "It is impossible for time to go backward, therefore...", - "You cannot put negative value of duration: (" + durationMillis + ")", + "You cannot put negative value of duration: (" + duration + ")", "as argument of timer methods (after(), timeout())", "" )); diff --git a/src/main/java/org/mockito/internal/util/Timer.java b/src/main/java/org/mockito/internal/util/Timer.java index 783f580c92..650e887660 100644 --- a/src/main/java/org/mockito/internal/util/Timer.java +++ b/src/main/java/org/mockito/internal/util/Timer.java @@ -6,38 +6,42 @@ import static org.mockito.internal.exceptions.Reporter.cannotCreateTimerWithNegativeDurationTime; +import java.time.Duration; +import java.time.Instant; + public class Timer { - private final long durationMillis; - private long startTime = -1; + private final Duration duration; + private Instant startTime = null; - public Timer(long durationMillis) { - validateInput(durationMillis); - this.durationMillis = durationMillis; + public Timer(Duration duration) { + validateInput(duration); + this.duration = duration; } /** * Informs whether the timer is still counting down. */ public boolean isCounting() { - assert startTime != -1; - return System.currentTimeMillis() - startTime <= durationMillis; + assert startTime != null; + Duration elapsed = Duration.between(startTime, Instant.now()); + return elapsed.compareTo(duration) <= 0; } /** * Starts the timer count down. */ public void start() { - startTime = System.currentTimeMillis(); + startTime = Instant.now(); } - private void validateInput(long durationMillis) { - if (durationMillis < 0) { - throw cannotCreateTimerWithNegativeDurationTime(durationMillis); + private void validateInput(Duration duration) { + if (duration.isNegative()) { + throw cannotCreateTimerWithNegativeDurationTime(duration); } } - public long duration() { - return durationMillis; + public Duration duration() { + return duration; } } diff --git a/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java b/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java index 24ec61a90d..edcf77cf62 100644 --- a/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java +++ b/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java @@ -4,6 +4,8 @@ */ package org.mockito.internal.verification; +import java.time.Duration; + import org.mockito.exceptions.base.MockitoAssertionError; import org.mockito.internal.util.Timer; import org.mockito.internal.verification.api.VerificationData; @@ -11,12 +13,12 @@ /** * Verifies that another verification mode (the delegate) is satisfied within a certain timeframe - * (before timeoutMillis has passed, measured from the call to verify()), and either returns immediately + * (before timeout has passed, measured from the call to verify()), and either returns immediately * once it does, or waits until it is definitely satisfied once the full time has passed. */ public class VerificationOverTimeImpl implements VerificationMode { - private final long pollingPeriodMillis; + private final Duration pollingPeriod; private final VerificationMode delegate; private final boolean returnOnSuccess; private final Timer timer; @@ -24,22 +26,22 @@ public class VerificationOverTimeImpl implements VerificationMode { /** * Create this verification mode, to be used to verify invocation ongoing data later. * - * @param pollingPeriodMillis The frequency to poll delegate.verify(), to check whether the delegate has been satisfied - * @param durationMillis The max time to wait (in millis) for the delegate verification mode to be satisfied + * @param pollingPeriod The frequency to poll delegate.verify(), to check whether the delegate has been satisfied + * @param duration The max time to wait for the delegate verification mode to be satisfied * @param delegate The verification mode to delegate overall success or failure to * @param returnOnSuccess Whether to immediately return successfully once the delegate is satisfied (as in * {@link org.mockito.verification.VerificationWithTimeout}, or to only return once * the delegate is satisfied and the full duration has passed (as in * {@link org.mockito.verification.VerificationAfterDelay}). */ - public VerificationOverTimeImpl(long pollingPeriodMillis, long durationMillis, VerificationMode delegate, boolean returnOnSuccess) { - this(pollingPeriodMillis, delegate, returnOnSuccess, new Timer(durationMillis)); + public VerificationOverTimeImpl(Duration pollingPeriod, Duration duration, VerificationMode delegate, boolean returnOnSuccess) { + this(pollingPeriod, delegate, returnOnSuccess, new Timer(duration)); } /** * Create this verification mode, to be used to verify invocation ongoing data later. * - * @param pollingPeriodMillis The frequency to poll delegate.verify(), to check whether the delegate has been satisfied + * @param pollingPeriod The frequency to poll delegate.verify(), to check whether the delegate has been satisfied * @param delegate The verification mode to delegate overall success or failure to * @param returnOnSuccess Whether to immediately return successfully once the delegate is satisfied (as in * {@link org.mockito.verification.VerificationWithTimeout}, or to only return once @@ -47,8 +49,8 @@ public VerificationOverTimeImpl(long pollingPeriodMillis, long durationMillis, V * {@link org.mockito.verification.VerificationAfterDelay}). * @param timer Checker of whether the duration of the verification is still acceptable */ - public VerificationOverTimeImpl(long pollingPeriodMillis, VerificationMode delegate, boolean returnOnSuccess, Timer timer) { - this.pollingPeriodMillis = pollingPeriodMillis; + public VerificationOverTimeImpl(Duration pollingPeriod, VerificationMode delegate, boolean returnOnSuccess, Timer timer) { + this.pollingPeriod = pollingPeriod; this.delegate = delegate; this.returnOnSuccess = returnOnSuccess; this.timer = timer; @@ -97,7 +99,7 @@ public void verify(VerificationData data) { private AssertionError handleVerifyException(AssertionError e) { if (canRecoverFromFailure(delegate)) { - sleep(pollingPeriodMillis); + sleep(pollingPeriod); return e; } else { throw e; @@ -109,12 +111,12 @@ protected boolean canRecoverFromFailure(VerificationMode verificationMode) { } public VerificationOverTimeImpl copyWithVerificationMode(VerificationMode verificationMode) { - return new VerificationOverTimeImpl(pollingPeriodMillis, timer.duration(), verificationMode, returnOnSuccess); + return new VerificationOverTimeImpl(pollingPeriod, timer.duration(), verificationMode, returnOnSuccess); } - private void sleep(long sleep) { + private void sleep(Duration sleep) { try { - Thread.sleep(sleep); + Thread.sleep(sleep.toMillis()); } catch (InterruptedException ie) { throw new RuntimeException("Thread sleep has been interrupted", ie); } @@ -124,8 +126,8 @@ public boolean isReturnOnSuccess() { return returnOnSuccess; } - public long getPollingPeriodMillis() { - return pollingPeriodMillis; + public Duration getPollingPeriod() { + return pollingPeriod; } public Timer getTimer() { diff --git a/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java b/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java index 87d9076e00..0f3845b6cd 100644 --- a/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java +++ b/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java @@ -35,7 +35,7 @@ private VerificationMode wrapInOrder(VerificationWrapper verificationWrapper, if (verificationMode instanceof VerificationOverTimeImpl) { final VerificationOverTimeImpl verificationOverTime = (VerificationOverTimeImpl)verificationMode; if (verificationOverTime.isReturnOnSuccess()) { - return new VerificationOverTimeImpl(verificationOverTime.getPollingPeriodMillis(), + return new VerificationOverTimeImpl(verificationOverTime.getPollingPeriod(), verificationOverTime.getTimer().duration(), wrapInOrder(verificationWrapper, verificationOverTime.getDelegate(), inOrder), verificationOverTime.isReturnOnSuccess()); diff --git a/src/main/java/org/mockito/verification/After.java b/src/main/java/org/mockito/verification/After.java index 54d7453022..a65a244ef7 100644 --- a/src/main/java/org/mockito/verification/After.java +++ b/src/main/java/org/mockito/verification/After.java @@ -4,6 +4,8 @@ */ package org.mockito.verification; +import java.time.Duration; + import org.mockito.internal.verification.VerificationOverTimeImpl; import org.mockito.internal.verification.VerificationWrapper; @@ -20,13 +22,25 @@ public class After extends VerificationWrapper impleme *

* Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class. * See javadoc for {@link VerificationWithTimeout} + * @deprecated Use {@link After#After(Duration, VerificationMode)} instead. */ + @Deprecated public After(long delayMillis, VerificationMode verificationMode) { - this(10, delayMillis, verificationMode); + this(Duration.ofMillis(delayMillis), verificationMode); + } + + /** + * See the javadoc for {@link VerificationAfterDelay} + *

+ * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class. + * See javadoc for {@link VerificationWithTimeout} + */ + public After(Duration delay, VerificationMode verificationMode) { + this(Duration.ofMillis(10), delay, verificationMode); } - After(long pollingPeriod, long delayMillis, VerificationMode verificationMode) { - this(new VerificationOverTimeImpl(pollingPeriod, delayMillis, verificationMode, false)); + After(Duration pollingPeriod, Duration delay, VerificationMode verificationMode) { + this(new VerificationOverTimeImpl(pollingPeriod, delay, verificationMode, false)); } After(VerificationOverTimeImpl verificationOverTime) { diff --git a/src/main/java/org/mockito/verification/Timeout.java b/src/main/java/org/mockito/verification/Timeout.java index 99dcc45f53..b7679abf26 100644 --- a/src/main/java/org/mockito/verification/Timeout.java +++ b/src/main/java/org/mockito/verification/Timeout.java @@ -6,6 +6,8 @@ import static org.mockito.internal.exceptions.Reporter.atMostAndNeverShouldNotBeUsedWithTimeout; +import java.time.Duration; + import org.mockito.internal.util.Timer; import org.mockito.internal.verification.VerificationOverTimeImpl; import org.mockito.internal.verification.VerificationWrapper; @@ -23,23 +25,35 @@ public class Timeout extends VerificationWrapper imple *

* Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class. * See javadoc for {@link VerificationWithTimeout} + * @deprecated Use {@link Timeout#Timeout(Duration, VerificationMode)} instead. */ + @Deprecated public Timeout(long millis, VerificationMode delegate) { - this(10, millis, delegate); + this(Duration.ofMillis(millis), delegate); + } + + /** + * See the javadoc for {@link VerificationWithTimeout} + *

+ * Typically, you won't use this class explicitly. Instead use timeout() method on Mockito class. + * See javadoc for {@link VerificationWithTimeout} + */ + public Timeout(Duration timeout, VerificationMode delegate) { + this(Duration.ofMillis(10), timeout, delegate); } /** * See the javadoc for {@link VerificationWithTimeout} */ - Timeout(long pollingPeriodMillis, long millis, VerificationMode delegate) { - this(new VerificationOverTimeImpl(pollingPeriodMillis, millis, delegate, true)); + Timeout(Duration pollingPeriod, Duration timeout, VerificationMode delegate) { + this(new VerificationOverTimeImpl(pollingPeriod, timeout, delegate, true)); } /** * See the javadoc for {@link VerificationWithTimeout} */ - Timeout(long pollingPeriodMillis, VerificationMode delegate, Timer timer) { - this(new VerificationOverTimeImpl(pollingPeriodMillis, delegate, true, timer)); + Timeout(Duration pollingPeriod, VerificationMode delegate, Timer timer) { + this(new VerificationOverTimeImpl(pollingPeriod, delegate, true, timer)); } Timeout(VerificationOverTimeImpl verificationOverTime) { diff --git a/src/test/java/org/mockito/internal/util/TimerTest.java b/src/test/java/org/mockito/internal/util/TimerTest.java index 8a4a173e02..2f2885b0da 100644 --- a/src/test/java/org/mockito/internal/util/TimerTest.java +++ b/src/test/java/org/mockito/internal/util/TimerTest.java @@ -4,6 +4,8 @@ */ package org.mockito.internal.util; +import java.time.Duration; + import org.assertj.core.api.Assertions; import org.junit.Rule; import org.junit.Test; @@ -18,7 +20,7 @@ public class TimerTest extends TestBase { @Test public void should_return_true_if_task_is_in_acceptable_time_bounds() { //given - long duration = 10000L; + Duration duration = Duration.ofSeconds(10); Timer timer = new Timer(duration); //when @@ -31,7 +33,7 @@ public void should_return_true_if_task_is_in_acceptable_time_bounds() { @Test public void should_return_false_when_time_run_out() throws Exception { //given - Timer timer = new Timer(0); + Timer timer = new Timer(Duration.ZERO); timer.start(); //when @@ -45,7 +47,7 @@ public void should_return_false_when_time_run_out() throws Exception { public void should_throw_friendly_reminder_exception_when_duration_is_negative() { expectedException.expect(FriendlyReminderException.class); expectedException.expectMessage("Don't panic! I'm just a friendly reminder!"); - new Timer(-1); + new Timer(Duration.ofMillis(-1)); } private void oneMillisecondPasses() throws InterruptedException { diff --git a/src/test/java/org/mockito/internal/verification/VerificationOverTimeImplTest.java b/src/test/java/org/mockito/internal/verification/VerificationOverTimeImplTest.java index 82cceeaea7..5f206c5420 100644 --- a/src/test/java/org/mockito/internal/verification/VerificationOverTimeImplTest.java +++ b/src/test/java/org/mockito/internal/verification/VerificationOverTimeImplTest.java @@ -9,6 +9,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.initMocks; +import java.time.Duration; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -29,7 +31,8 @@ public class VerificationOverTimeImplTest { @Before public void setUp() { initMocks(this); - impl = new VerificationOverTimeImpl(10, 1000, delegate, true); + impl = new VerificationOverTimeImpl( + Duration.ofMillis(10), Duration.ofSeconds(1), delegate, true); } @Test diff --git a/src/test/java/org/mockito/verification/TimeoutTest.java b/src/test/java/org/mockito/verification/TimeoutTest.java index ae6e5d2e84..3719ae4215 100644 --- a/src/test/java/org/mockito/verification/TimeoutTest.java +++ b/src/test/java/org/mockito/verification/TimeoutTest.java @@ -7,6 +7,8 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.*; +import java.time.Duration; + import org.junit.Test; import org.mockito.InOrder; import org.mockito.Mock; @@ -28,7 +30,7 @@ public class TimeoutTest extends TestBase { @Test public void should_pass_when_verification_passes() { - Timeout t = new Timeout(1, mode, timer); + Timeout t = new Timeout(Duration.ofMillis(1), mode, timer); when(timer.isCounting()).thenReturn(true); doNothing().when(mode).verify(data); @@ -42,7 +44,7 @@ public void should_pass_when_verification_passes() { @Test public void should_fail_because_verification_fails() { - Timeout t = new Timeout(1, mode, timer); + Timeout t = new Timeout(Duration.ofMillis(1), mode, timer); when(timer.isCounting()).thenReturn(true, true, true, false); doThrow(error). @@ -60,7 +62,7 @@ public void should_fail_because_verification_fails() { @Test public void should_pass_even_if_first_verification_fails() { - Timeout t = new Timeout(1, mode, timer); + Timeout t = new Timeout(Duration.ofMillis(1), mode, timer); when(timer.isCounting()).thenReturn(true, true, true, false); doThrow(error). @@ -74,7 +76,7 @@ public void should_pass_even_if_first_verification_fails() { @Test public void should_try_to_verify_correct_number_of_times() { - Timeout t = new Timeout(10, mode, timer); + Timeout t = new Timeout(Duration.ofMillis(10), mode, timer); doThrow(error).when(mode).verify(data); when(timer.isCounting()).thenReturn(true, true, true, true, true, false); diff --git a/src/test/java/org/mockitousage/verification/VerificationWithTimeoutTest.java b/src/test/java/org/mockitousage/verification/VerificationWithTimeoutTest.java index 0c50578f6c..230b632910 100644 --- a/src/test/java/org/mockitousage/verification/VerificationWithTimeoutTest.java +++ b/src/test/java/org/mockitousage/verification/VerificationWithTimeoutTest.java @@ -10,6 +10,7 @@ import static org.mockito.junit.MockitoJUnit.rule; import static org.mockitoutil.Stopwatch.createNotStarted; +import java.time.Duration; import java.util.concurrent.TimeUnit; import org.assertj.core.api.Assertions; @@ -57,6 +58,17 @@ public void should_verify_with_timeout() { verify(mock).oneArg('c'); //sanity check } + @Test + public void should_verify_with_timeout_duration() { + // when + async.runAfter(50, callMock('c')); + async.runAfter(500, callMock('c')); + + // then + verify(mock, timeout(Duration.ofMillis(200)).only()).oneArg('c'); + verify(mock).oneArg('c'); //sanity check + } + @Test public void should_verify_with_timeout_and_fail() { // when @@ -72,6 +84,21 @@ public void call() { //TODO let's have a specific exception vs. generic assertion error + message } + @Test + public void should_verify_with_timeout_and_fail_duration() { + // when + async.runAfter(200, callMock('c')); + + // then + Assertions.assertThatThrownBy(new ThrowableAssert.ThrowingCallable() { + @Override + public void call() { + verify(mock, timeout(Duration.ofMillis(50)).only()).oneArg('c'); + } + }).isInstanceOf(AssertionError.class).hasMessageContaining("Wanted but not invoked"); + //TODO let's have a specific exception vs. generic assertion error + message + } + @Test @Ignore //TODO nice to have public void should_verify_with_timeout_and_fail_early() {