TestScheduler, Concat and Do
-
Wednesday, March 28, 2012 4:48 PM
Hello,
I have a ViewModel that subscribes to a client connection event.
When the event is raised, I serialize the call to 5 client methods using Concat.
When a method returns, I update some progress indicators.
This works fine in production (with real objects). Notice that I do not use ObserveOnScheduler, but rather ObserveOn.
In production, I inject the DispatcherScheduler, and in tests, a TestScheduler.
_Client.Connected.Do(t => { SetProgress(0, "Starting"); _Client.Method1() .Do(v => SetProgress(20, "Text info")) .Concat<object>(_Client.Method2() .Do(u => SetProgress(40, "Text info"))) .Concat<object>(_Client.Method3() .Do(u => SetProgress(60, "Text info"))) .Concat<object>(_Client.Method4() .Do(u => SetProgress(80, "Text info"))) .Concat<object>(_Client.Method5() .ObserveOn(dispatcherScheduler) .Do(u => { SetProgress(100, "Done!"); //...Update UI consequently })).Subscribe(); }).Subscribe();Now, I created a Unit Test to verify that when the client connected event is raised, all 5 methods are called and at the
end the progress indicators are set to 100 and Done!To do this, I used a TestScheduler to setup observables for a fake client. I used Moq to verify that the method were called,
and some assertions at the end to verify the progress indicators.
The code looks like this:
[Test] public void GetStuffFromClientWhenConnected() { _ClientMock.SetupGet(t => t.Connected) .Returns(_DispatcherScheduler.CreateHotObservable(ReactiveTest.OnNext(1, new EventPattern<EventArgs>(null, null)))); _ClientMock.Setup(t => t.Method1()) .Returns(_DispatcherScheduler.CreateHotObservable(ReactiveTest.OnNext(3, new FakeData()))); _ClientMock.Setup(t => t.Method2()) .Returns(_DispatcherScheduler.CreateHotObservable(ReactiveTest.OnNext(4, new FakeData()))); _ClientMock.Setup(t => t.Method3()) .Returns(_DispatcherScheduler.CreateHotObservable(ReactiveTest.OnNext(5, new FakeData()))); _ClientMock.Setup(t => t.Method4()) .Returns(_DispatcherScheduler.CreateHotObservable(ReactiveTest.OnNext(6, new FakeData()))); _ClientMock.Setup(t => t.Method5()) .Returns(_DispatcherScheduler.CreateHotObservable(ReactiveTest.OnNext(7, new FakeData()))); var vm = CreateViewModel(); _DispatcherScheduler.AdvanceTo(8); _ClientMock.Verify(t => t.Method1()); _ClientMock.Verify(t => t.Method2()); _ClientMock.Verify(t => t.Method3()); _ClientMock.Verify(t => t.Method4()); _ClientMock.Verify(t => t.Method5()); Assert.That(vm.Progress, Is.EqualTo(100)); Assert.That(vm.ProgressText, Is.EqualTo("Done")); }
The connected event is raised, the 5 methods are called, but the progress indicators stay at 20, "Text Info".
I wonder why. I registered and raised these events using the TestScheduler.AdvanceTo(8).
It looks like only Method1 completed event was raised.
Any advice?
Regards
Louis-Pierre Beaumont- Edited by Louis-Pierre Beaumont Wednesday, March 28, 2012 4:50 PM
All Replies
-
Wednesday, March 28, 2012 5:37 PM
Well,
I'm going to answer my own question.
I'll give credit to Dave Sexton too, as he wrote part of the answer in a post named Reactive Framework - Chaining
I simply rewrote my big Concat + Do statement, using SelectMany instead.
It now works in both tests and production, and looks much more elegant.
- Marked As Answer by Louis-Pierre Beaumont Wednesday, March 28, 2012 5:37 PM
- Edited by Louis-Pierre Beaumont Wednesday, March 28, 2012 5:38 PM

