I'm trying to test that my custom IProgress is doing what I expect it to do: "Report" the current status after every second.
So I have some code but it's always failing. But this is the kicker - it's only failing when I have hardly any code in the test case.
If I add in one more piece of code to the test (which is commented out in the repo) .. it works if I uncomment that.
It's like .. something needs to get fired off .. but it hasn't completed before the "assertions" are checked.
Full fiddle: https://dotnetfiddle.net/qXHzlx
Here's the code:
// Arrange.
var reportValue = 0;
var progress = new TimerProgress<int>((int value) => reportValue = value);
await Task.Delay(TimeSpan.FromSeconds(2)); // Need to wait more than 1 second for the report to work.
// Act.
progress.Report(5);
// Assert.
reportValue.ShouldBe(5);
and the custom TimerProgress :
public class TimerProgress<T> : IProgress<T>
{
    private readonly TimeSpan _intervalInMilliseconds;
    private readonly IProgress<T> _progress;
    private DateTime? _lastReportedOn;
    public TimerProgress(Action<T> handler, double intervalInMillieconds = 1000)
    {
        if (intervalInMillieconds <= 0)
        {
            throw new ArgumentOutOfRangeException(nameof(intervalInMillieconds));
        }
        _intervalInMilliseconds = TimeSpan.FromMilliseconds(intervalInMillieconds);
        _progress = new Progress<T>(handler);
        _lastReportedOn = DateTime.UtcNow;
    }
    public void Report(T value)
    {
        var now = DateTime.UtcNow;
        if (now - _lastReportedOn > _intervalInMilliseconds)
        {
            // We're due for a report!
            _progress.Report(value);
        }
        _lastReportedOn = now;
    }
}
With the test case, I expect:
- new 
TimeProgressinstance.Nowis "remembered". - Wait 2 seconds (you'll see why in a tick)
 - "Report". This now checks to see if 
remembered-nowis over 1 second ago. It should be because we've waited for 2 seconds! So now, we should "report" - Handler gets called .. which 'remembers' the number 5
 - we now assert that '5' was ended up getting reported.
 
So I keep getting a failure assertion saying the value is 0, not 5.
But when I add one more line of code to the test, then the value is now 5.
Is this about a timing or event firing issue?
Is this about how my handler is trying to update a variable outside of the handler, which is Bad™️ ?
Edit
Suggestions from people are saying that the Progress<T> actually uses a sync context under the hood and this is the issue?