TestScheduler, Concat and Do


  • 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");
    		.Do(v => SetProgress(20, "Text info"))
    				       .Do(u => SetProgress(40, "Text info")))
    				       .Do(u => SetProgress(60, "Text info")))
    				       .Do(u => SetProgress(80, "Text info")))
    				       .Do(u =>
    				       		SetProgress(100, "Done!");
    				       		//...Update UI consequently

    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:

    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();
    	_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?

    Louis-Pierre Beaumont

    quarta-feira, 28 de março de 2012 16:48