Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Unit test BackgroundWorker C#

I'm trying to unit test, using VS unit testing facility following method.

void Get(string name, Action<string> callBack);

here is unit tester

    [TestMethod]
    public void Test()
    {
        Action<string> cb = name =>
        {
            Assert.IsNotNull(name);
        };

        var d = new MyClass();
        d.Get("test", cb);
    }

The only problem is that internal implementation uses BackgroundWorker, hence callback is invoked on another thread. Here is internal implementation.

    public void Get(string name, Action<string> callBack)
    {
        callBackString = callBack;
        GetData(name);
    }  

    private void GetData(string name)
    {
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += bw_DoWork;
        bw.RunWorkerCompleted += bw_RunWorkerCompleted;
        bw.RunWorkerAsync(name);
    }

    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //do work here
        if (null != callBackString)
            callBackString("ok");
    }

Of course because Get() returns right away, test completes with success and testing stops, thus RunWorkerCompleted never gets to be executed. I can easily test this via normal application (WPF) because it stays running, yet I'd like to have ability to unit test this.

Any ideas? Thanks in advance.

like image 513
Sherlock Avatar asked Sep 11 '09 14:09

Sherlock


2 Answers

Something like:

[TestMethod]
public void Test()
{   
    bool running = true;
    string result = null;

    Action<string> cb = name =>
    {
        result = name;
        running = false;
    };

    var d = new MyClass();
    d.Get("test", cb);

    while(running)
    {
        Thread.Sleep(100);
    }

    Assert.IsNotNull(result);
}

Though you probably want to add something in there to stop the test from running forever if it fails...

like image 160
Martin Harris Avatar answered Nov 14 '22 21:11

Martin Harris


I don't know the details for C# & BackgroundWorker but I'd do this by injecting the BackgroundWorker implementation and during the test use a stubbed BackgroundWorker that you can control when it executions and in which thread. If communication between two threads is required then have the stubbed BackgroundWorker create a new thread and have the test pause until it is complete, if not force it to run after the call to get.

like image 44
Michael Lloyd Lee mlk Avatar answered Nov 14 '22 22:11

Michael Lloyd Lee mlk