Rx .Net TestScheduler- executing immediately scheduled events

Solution 1:

You might want to consider how you are using the TestScheduler:

It will in general execute at the due time. For example, this code will write to the Console:

var scheduler = new TestScheduler();

scheduler.Schedule(
    TimeSpan.FromTicks(100),
    () => Console.WriteLine("Hello"));

scheduler.AdvanceTo(100);

However, TestScheduler will only inspect it's queue when time is moved. So if you schedule an action, you need to move time via AdvanceBy, AdvanceTo or Start to get it to process the queue. When it does, it will process everything up to the current time. E.g. Even this will output to the console despite scheduling "in the past":

var scheduler = new TestScheduler();

scheduler.AdvanceTo(TimeSpan.FromTicks(100).Ticks);

scheduler.Schedule(
    DateTime.MinValue + TimeSpan.FromTicks(50),
    () => Console.WriteLine("Hello"));

Console.WriteLine("No output until the scheduler is given time...");
scheduler.AdvanceBy(1);

Idiomatic use of TestScheduler usually involves queuing up all your work and then running to completion via a Start() call and then checking for expected state. Use of AdvanceBy, AdvanceTo tends to be for more demanding test scenarios where you need to test some intermediate state - and even then you generally queue everything up first with appropriate due times and then AdvanceBy or AdvanceTo your time of interest, check state, and then progress again with AdvanceBy, AdvanceTo or Start.

What you don't want to do generally is queue work, run a bit, queue more work, run a bit - especially if you are scheduling without a due time. Then you will hit the problem you have here.

That's not to say in your specific scenario this may be unavoidable - if you need to make decisions about what to schedule after a particular time for example - but consider if you can set everything up in advance as it's probably going to result in cleaner test code that more closely follows the Arrange Act Assert pattern.

I try to Arrange by scheduling, then Act by moving time, then Assert the results.

Solution 2:

use AdvanceBy(1) to advance the scheduler by 1 tick. The scheduler only executes events when the clock actually advances.

Different schedulers behave differently when you schedule something for immediate execution. Some of them really do execute it immediately. Some put it in a queue to be executed at the first available opportunity.

There's not a good way for the TestScheduler to behave in this situation unless the API is modified to let you tell it which way it should behave.