Unit testing a ReactiveUI ViewModel

This is a quick post about unit testing a view model that uses ReactiveUI. More specifically it’s about testing the MessageBus code within the view model.

So the scenario is simple. I have a view model (of type ConfigurationViewModel) when anything in the application wishes to delete configuration data it sends the appropriate message onto the ReactiveUI MessageBus and the idea is that the configuration view model then correctly calls the delete method on its underlying configuration class. I’m using RhinoMocks to mock the underlying configuration class in the test below.

[Test]
public void DeleteConfiguration_ShouldCallUnderlyingObjectToDeleteProject()
{
   using (mocks.Record())
   {
      Expect.Call(() => configuration.Delete("MyProject"));
   }

   using (mocks.Playback())
   {
      MessageBus.Current.SendMessage(new ProjectViewModel("MyProject", false, false), "Delete");
   }
}

Now this worked perfectly so I happily moved onto another similar test for another part of the configuration. I ran up the tests after implementing the code and one of the tests failed. I ran the single test again now moving from ReSharper’s test runner to NUnit’s. The test passed. I ran all tests and again it failed.

After some reading/searching around I found a post on StackOverflow where Paul Betts mentions the RxApp.DeferredScheduler is exactly that, deferred. After a bit of testing I realised then that I needed to switch this to an ImmediateScheduler to resolve the issues. Once I did this everything worked perfectly.

So the note to myself is to add the code

[SetUp]
public void SetUp()
{
   RsApp.DeferredScheduler = Scheduler.Immediate;

   // setup the mocks etc.
}

A small postscript to the above is that after reading the ReactiveUI code on GITHUB I realised that it attempts to automatically switch the DeferredSchduler to Immediate if it detects it’s being run from a test runner. I removed the above code (in the SetUp) and indeed it all worked fine now. So I’m note quite sure what caused the problem previously, but at least I learned how to solve it if it occurs again.