Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test IObservable<T> with ObserveOnDispatcher

I need to test piece of code

        var watcher = new FakeIFileSystemWatcher();
        watcher.FilesToBeImported
            .ObserveOnDispatcher()
            .Subscribe(list.Add);

so I created this little unit test but I can't make it pass cause list.Count is always 0

    [Test]
    public void Foo()
    {
        var list = new List<string>();

        var watcher = new FakeIFileSystemWatcher();
        watcher.FilesToBeImported
            .ObserveOnDispatcher()
            .Subscribe(list.Add);

        Task task = Task.Factory.StartNew(() =>
        {                
            watcher.AddFile("cc");
            watcher.AddFile("cc");
            watcher.AddFile("cc");
        }, TaskCreationOptions.LongRunning);
        Task.WaitAll(task);

        Assert.AreEqual(3, list.Count);
    }

if I comment out the method

            .ObserveOnDispatcher()

it pass but how can I get it working also with ObserveOnDispatcher() ?

like image 432
jitidea Avatar asked Jul 04 '12 15:07

jitidea


People also ask

Can you use a for loop in a unit test?

Yes you can have loops in unit test, but with caution. As mentioned by Alex York, loops are acceptable if you test one thing; i.e. one expectation. If you use loops, then I recommend that you must do two things: As mentioned above, test for a non-empty iteration set.

How do I run a MSTest unit test?

To run MSTest unit tests, specify the full path to the MSTest executable (mstest.exe) in the Unit Testing Options dialog. To call this dialog directly from the editor, right-click somewhere in the editor and then click Options.

What can we test with unit tests?

The purpose of a unit test in software engineering is to verify the behavior of a relatively small piece of software, independently from other parts. Unit tests are narrow in scope, and allow us to cover all cases, ensuring that every single part works correctly.


2 Answers

If you use ObserveOnDispatcher you create a dependency to the "dispatcher" which means that you need a window and a message loop. To get around this problem in a unit test you can instead use the ObserveOn method that uses a scheduler and then use dependency injection to inject the correct scheduler. For unit testing you could use Scheduler.Immediate and for the actual application you could use DispatcherScheduler.Instance. Notice that there also exists a TestScheduler which is really useful for running unit tests in virtual time.

like image 79
Martin Liversage Avatar answered Sep 19 '22 01:09

Martin Liversage


I solved using the class DispatcherUtil I found here Using the WPF Dispatcher in unit tests

now my code is the following

    [Test]
    public void Foo()
    {
        var list = new List<string>();

        var watcher = new FakeIFileSystemWatcher();
        watcher.FilesToBeImported
            .ObserveOnDispatcher()
            .Subscribe(list.Add);

        Task task = Task.Factory.StartNew(() =>
        {
            watcher.AddFile("cc");
            watcher.AddFile("cc");
            watcher.AddFile("cc");
            watcher.AddFile("cc");
        }, TaskCreationOptions.LongRunning);
        Task.WaitAll(task);
        DispatcherUtil.DoEvents();
        Assert.AreEqual(4, list.Count);
    }

and it works like a charm

like image 21
jitidea Avatar answered Sep 23 '22 01:09

jitidea