Delayed Constraint
DelayedConstraint delays evaluation of another constraint, optionally polling until the constraint passes or the
timeout expires. This is useful for testing asynchronous operations or eventual consistency.
Usage
<constraint>.After(int delayInMilliseconds)
<constraint>.After(int delayInMilliseconds, int pollingInterval)
<constraint>.After(int delay).Seconds
<constraint>.After(int delay).Minutes.PollEvery(int interval).MilliSeconds
Examples
[Test]
public void DelayedConstraint_Examples()
{
var flag = 0; // Use int for Interlocked
Task.Run(async () =>
{
await Task.Delay(50);
Interlocked.Exchange(ref flag, 1);
});
// Poll until condition is true (or timeout)
Assert.That(() => Interlocked.CompareExchange(ref flag, 0, 0) == 1,
Is.True.After(500).MilliSeconds.PollEvery(50).MilliSeconds);
}
Fluent Time Syntax
[Test]
public void DelayedConstraint_Fluent_Examples()
{
var counter = 0;
Task.Run(async () =>
{
await Task.Delay(50);
Interlocked.Exchange(ref counter, 10);
});
// Fluent time syntax
Assert.That(() => Interlocked.CompareExchange(ref counter, 0, 0),
Is.GreaterThan(0).After(1).Seconds.PollEvery(100).MilliSeconds);
}
Time Modifiers
.Seconds
.Minutes
.MilliSeconds // Note capital 'S'
Default unit is milliseconds when no modifier is specified.
Notes
- Use delegates (
() => value) not direct values, since values are captured at call time. - When polling, the delegate may be called multiple times - avoid side effects.
- The
.After()modifier applies to the entire constraint expression preceding it. - Without polling, the constraint waits the full delay before checking once.
See Also
- Throws Constraint - For exception testing
- True Constraint - For boolean conditions