Damian Mehers' Blog Android, VR and Wearables from Geneva, Switzerland.

6Mar/082

Handling background threads using NUnit and Rhino Mocks

I've just started using NUnit and Rhino Mocks, so this is not necessarily the best way to do things, but it works for me.

I have a class which has a method which kicks off a background thread.  This thread has an infinite loop -- for each loop it accepts a request and services the request.

I needed to test an instance of the class, for one specific incoming request.  There are two issues -- how to know when the object's background thread has finished servicing the request, and how to stop the background thread from looping back and accepting another request.

This is what I ended up doing:

[TestFixture]
public class ServerTest {

  [Test]
  public void SomeTest() {

    bool done = false;

    MockRepository mocks = new MockRepository();

    using(mocks.Record()) {

      // ... lots of 'Expects'

      // This is the final call which gets made in the background thread
      // to complete the handling of the request
      Expect.Call(someObject.LastMethod).Do((Expect.Action)delegate() {
        done = true;
        System.Threading.Thread.CurrentThread.Abort();
      });
    }
    using(mocks.Playback()) {
      Server server = new Server();
      server.Start();
      int count = 0;
      while(!done && count < 10) {
        System.Threading.Thread.Sleep(1000);
        count++;
      }
    }
  }
}

The key point is that in the test's action associated with the last method that gets invoked as part of your background thread's processing loop, you need to set a flag so that the test knows that the last method has executed, and also abort the current thread so that the background thread doesn't loop back, and consume another request.

Comments (2) Trackbacks (0)
  1. Coincidently I recently wrote a post about this issue and another way to solve it http://journalofasoftwaredev.wordpress.com/2008/03/05/unit-testing-threading-using-rhino-mocks/

  2. Thanks Michael — looks cool — your use of the ManualResetEvent is a lot more elegant too!


Leave a comment

No trackbacks yet.