-
-
Notifications
You must be signed in to change notification settings - Fork 96
Description
I was wondering if there was any interest in providing assertions that wait for state (with a timeout).
For context, I'm writing some code that raises events on a fake GPIO controller. The events can take some milliseconds to raise up which changes the value of the return of a method.
I tried to apply .CompletesWithin(), but unfortunately that is only waiting for the method to complete - it doesn't try to wait for the assertion to pass.
// Doesn't pass.
await Assert.That(() => sut.GetActivePins())
.CompletesWithin(TimeSpan.FromSeconds(5))
.IsEquivalentTo([2]);Here's an example (in my mind) that would work.
// Passes after 10ms.
await Assert.That(() => sut.GetActivePins())
.IsEquivalentTo([2])
.WaitFor(TimeSpan.FromSeconds(1));For inspiration, Egil Hansen's bUnit library (for testing Blazor components) has WaitForState and WaitForAssertion (link here).
Here's a tiny helper Im using to get around this right at this moment. It's not elegant and sort of bypasses (and obscures) the actual assertion.
internal static class WaitFor
{
public static async Task<bool> Condition(Func<bool> predicate, int timeoutMs = 400, int pollMs = 10)
{
var start = Environment.TickCount;
while (!predicate())
{
if (Environment.TickCount - start > timeoutMs) return false;
await Task.Delay(pollMs);
}
return true;
}
}
// Within a test
var isValid = await WaitFor.Condition(() => sut.GetActivePins().SequenceEqual(expected));
await Assert.That(isValid).IsTrue();