I often use the RX Throttle method, which is brilliant for scenario’s such as allowing a user to type text into a textbox and then only calling my code when the user pauses typing for an assigned amount of time. Or when scrolling up and down lists and when the user stops selecting items getting more data for the selected item from a webservice or the likes.
But what do we do about testing such interactions ?
Sidetrack
Instead of looking at the Throttle method, I needed to create a Throttle that actually buffers the data sent to it and when the timeout occurs gives the subscriber all the data not just the last piece of data (as Throttle would). So here’s some code I wrote (based heavily upon a StackOverflow post)
This post is meant to be about how we test such code, so let’s look at one of the unit test I have for this
[Fact] public void ThrottleWithBuffer_EnsureValuesCorrectWhenOnNext() { var scheduler = new TestScheduler(); var expected = new[] { 'a', 'b', 'c' }; var actual = new List<List<char>>(); var subject = new Subject<char>(); subject.AsObservable(). ThrottleWithBuffer(TimeSpan.FromMilliseconds(500), scheduler). Subscribe(i => actual.Add(new List<char>(i))); scheduler.Schedule(TimeSpan.FromMilliseconds(100), () => subject.OnNext('a')); scheduler.Schedule(TimeSpan.FromMilliseconds(200), () => subject.OnNext('b')); scheduler.Schedule(TimeSpan.FromMilliseconds(300), () => subject.OnNext('c')); scheduler.Start(); Assert.Equal(expected, actual[0]); }
Now the key things here are the use of the TestScheduler which allows us the bend time (well not really, but it allows us to simulate the passing of time).
The TestScheduler is available in the Microsoft.Reactive.Testing.dll or from NuGet using Install-Package Rx-Testing
As you can see from the test, we now create the subscription to the observable and following that the scheduler is passed the “simulated” times. The first argument tells it the time an item is scheduled for, i.e. the first item is scheduled at 100ms, the next 200ms and finally 300ms. We then call Start on the scheduler to begin the time simulation.
Just think, if your code relied on something happening after a pause of a second then each test would have to wait one second before it could verify data, making a large test suit a lot slower to run. Using the TestScheduler we simply simulate a second passing.