I have a class called ValuePusher
with a property named Value
and receives a dependency of type ValueReceiver
, also with a property named Value
. The former class arranges to 'push' values to an instance of the latter class via a System.Reactive.Subjects.Subject<int>
object. Initially it pushes values one for one, but later it will restrict the amount of values pushed using the Sample
method - note the commented-out call to this method in the code below:
public sealed class ValuePusher : IDisposable
{
private readonly ValueReceiver _receiver;
private readonly IScheduler _scheduler;
private readonly Subject<int> _subject;
private int _value;
public ValuePusher(ValueReceiver receiver, IScheduler scheduler)
{
_receiver = receiver;
_scheduler = scheduler;
// Arrange to push values to `receiver` dependency
_subject = new Subject<int>();
_subject.ObserveOn(_scheduler)
//.Sample(TimeSpan.FromMilliseconds(50), _scheduler)
.SubscribeOn(_scheduler)
.Subscribe(i => PushCurrentValueToReceiver());
}
public int Value
{
get => _value;
set
{
_value = value;
_subject.OnNext(0);
}
}
private void PushCurrentValueToReceiver()
{
_receiver.Value = Value;
}
public void Dispose()
{
_subject?.OnCompleted();
_subject?.Dispose();
}
}
public class ValueReceiver
{
public int Value { get; set; }
}
I write a unit test for the code above, involving a Microsoft.Reactive.Testing.TestScheduler
, which passes:
[TestMethod]
[Timeout(1000)]
public void ReceiverReceivesValueFromPusherViaScheduler()
{
var scheduler = new TestScheduler();
var receiver = new ValueReceiver();
using (var pusher = new ValuePusher(receiver, scheduler))
{
scheduler.Start();
pusher.Value = 1;
scheduler.AdvanceBy(1);
Assert.AreEqual(1, receiver.Value);
}
}
However, if uncomment the call to Sample
method the test fails to complete and times-out. How can I change the test code or the production code to verify that values are pushed to the receiving object when Sample
is in use?
Source code: https://github.com/DanStevens/StackOverflow71409012
CodePudding user response:
The reason why it times out, seems to be the combination of .Sample(...)
and scheduler.Start()
.
scheduler.Start()
tries execute everything that has been scheduled, but I think Sample()
keeps scheduling a sample, and thus scheduler.Start()
never finishes.
So if you remove scheduler.Start()
, and do this instead:
...
// Following line instead of scheduler.Start(), needed because of the .SubscribeOn(...) call
scheduler.AdvanceBy(1);
pusher.Value = 1;
scheduler.AdvanceBy(TimeSpan.FromMilliseconds(50).Ticks);
Assert.AreEqual(1, receiver.Value);
...
it should work with or without the call to .Sample(...)
.
[Edit] as per Dan Stevens' comment.