I am using BackgroundWorker in a WPF application, in order to run long process in the background.
And I was trying to write unit tests for the class that use the BackgroundWorker.
I run into many problems getting those unit tests to work.
I tried first a simple approach, by calling the long process and do Thread.Sleep to wait for some times, to get the result back, and I tried with more other ways.
The unit tests were working when I run them from NUnit GUI, or from inside visual studio.
But when I check in , those tests will fail on the build server, which is configured with the continues integration.
Searching the web, I found the problem.
WPF, and all Windows desktop applications based on having only one GUI thread in a process.
When you call a background thread, and when the process finish on that thread, the thread tries to return to the GUI thread. And in case it doesn't find thread, then it will be terminated.
This is why the tests where running from the NUnit GUI, but not from the build server.
Because the thread were returning to the GUI and the values are being validated correctly.
So, what to do then?
There is a solution, which is forcing the background thread to return back to a specific thread.
I will describe this approach in a different thread.
But another approach which I like it better, is to have "Humble Executable"
The idea of the Humble Executable, is simple.
Don't test such classes.
Just as simple as avoid testing classes that call different thread.
So, if you have a class that call background threads, then take the code related to creating a second thread, to its own class, and make that class very thin, very shallow (Humble), so there will be nothing to test really.
And keep the business - related code, in a class that can be testable.

So, this is the approach I took eventually.
And here is a glimpse of the code that I built

So, in order to use the backgroundworker, I created a class called BackgroundWorkerWrapper
The interface of it looks like

public interface IBackgroundWorkerWrapper
{
       void DoWork(Func workToRun);
       void CancelAsync();
       event RunWorkerCompletedEventHandler WorkerCompleted;
}

and the implementation was as follows:

public class BackgroundWorkerWrapper : IBackgroundWorkerWrapper
{


      public event RunWorkerCompletedEventHandler WorkerCompleted;


       public void DoWork(Func workToRun)
       {
             BackgroundWorker _worker = new BackgroundWorker();
             _worker.DoWork += (sender, e) =>  { e.Result = workToRun.Invoke(); };
             _worker.RunWorkerCompleted += BackgroundWorkerCompleted;
        }


       void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            WorkerCompleted(sender, e);
        }
}

As you can see from the code above, the BackgroundWorkerWrapper, is very thin wrapper around the BackgroundWorker, and it has no logic to test.
it just call the code in the background, and raise the event when the backgroundworker raised its event.

and the class that does the process call, and handle the result, is calling the wrapper instead of directly calling the backgroundworker class.

And now in the unit test of that calling class, we can substitute the BackgroundWorkerWrapper by a mock object and raise the event WorkerCompleted;

So this is a simple of the unit test code that test the method that call the background process. (assuming I am using NMock2 for mocking the classes).

[Test]
public void TestMethodThatCallBackgroundProcess ()
{
     IBackgroundWorkerWrapper _wrapper;
    Mockery _mock = new Mockery();
    _wrapper = _mock.NewMock();
     CallingClass _callingClass = new CallingClass(_wrapper);
     Excpect.Once.On(_wrapper).Method("DoWork").WithAnyArgument());
     _callingClass.CallTheLongProcess();
     RunWorkerCompletedEventArgs e = new RunWorkerCompletedEventArgs("Successful", null, true);
     Fire.Event("WorkerCompleted").On(_worker).With(null, e);
}

The above code will simulate the background worker calling.

In later posts, I will describe another approach to actually run a unit test for the method that call the background worker process.