I'm dipping my toes in how to test multi-threaded stuff, but not quite sure how to get started. I'm sure I will figure more stuff out easier if I could just get stuff going, so I was wondering if someone could help me write an NUnit test case for this simple class:
class Worker
{
public event EventHandler<EventArgs> Done = (s, e) => { };
public void StartWork()
{
var thread = new Thread(Work) { Name = "Worker Thread" };
thread.Start();
}
private void Work()
{
// Do some heavy lifting
Thread.Sleep(500);
Done(this, EventArgs.Empty);
}
}
What I would like to test is simply: Is the Done
event raised when it finishes. I would have no problems if it was synchronous, but not sure where to even begin when it is not. A simple test if it wasn't multi-threaded (and the Work
method wasn't private) could be:
[TestFixture]
class WorkerTests
{
[Test]
public void DoWork_WhenDone_EventIsRaised()
{
var worker = new Worker();
var eventWasRaised = false;
worker.Done += (s, e) => eventWasRaised = true;
worker.Work();
Assert.That(eventWasRaised);
}
}
Any pointers?
You need to use a ManualResetEvent - see Unit Testing Multi-Threaded Asynchronous Events for more details.
Something like:
[Test]
public void DoWork_WhenDone_EventIsRaised()
{
var worker = new Worker();
var eventWasRaised = false;
var mre = new ManualResetEvent(false);
worker.Done += (s, e) => { eventWasRaised= true; mre.Set(); };
worker.Work();
mre.WaitOne(1000);
Assert.That(eventWasRaised);
}
The main problem you find with testing threaded apps is actually stimulating the thread with test data because you will need to block on the main thread to wait until the other thread exits.
The way we've worked with this is to test it synchronously as you suggest. This allows you to test the logical behaviour but it won't detect deadlocks and race conditions of course (not that testing can assert these things easily anyway).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With