1 minute read

When writing Unit Tests or Integration Tests for an API that exposes events, we need a way to validate that the events are called. The simplest approach would be to set a variable when the event is called. In the test itself we can sleep for a certain duration and check the variable:

public class Tests
{
    [Test]
    public void TestSubscription()
    {
        var flag = false;
        using var watcher  = _api.SubscribeToEvent(_ =>
        {
            flag = true;
        });

        Task.Delay(2000).Wait()
        Assert.That(flag);
    }
}

But this is not ideal. Firstly, if we set a low sleep value, the tests will sometimes fail based on latency and load on the machine. But then if we try to fix this by setting a high sleep duration, our test suite will become much much slower.

Instead, the better approach would be to use a synchronization mechanism like an AutoResetEvent. This allows us to wait until the event occurs. We can then set a high timeout in order to support edge cases and delays, but complete the test in a short time in 99% of the cases.

public class Tests
{
    [Test]
    public void TestSubscription()
    {
        var watchEvent = new AutoResetEvent(false);
        using var watcher  = _api.SubscribeToEvent(_ =>
        {
            watchEvent.Set();
        });

        Assert.That(watchEvent.WaitOne(2000));
    }
}

Updated: