Skip to content

Wait for state assertions #2984

@benjaminsampica

Description

@benjaminsampica

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();

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions