2

When testing event-driven code in C#, I would like to make sure my assertions don't execute until after the object under test has had a chance to handle an event. Currently, I am using an AutoResetEvent object to pause execution until an event is fired like this:

private MyClassDependency testObjectDependency = new MyClassDependency();
private MyClass testObject = new MyClass(testObjectDependency);
private AutoResetEvent eventLock = new AutoResetEvent(false);

void handle(object sender, EventArgs e)
{
    eventLock.Set();
}

[Test()]
public void DoSomethingTest()
{
    testObjectDependency.Event += handle;
    testObject.DoSomething();
    eventLock.WaitOne();
    testObjectDependency.Event -= handle;
    testObject.IsSomethingDone.Should().Be.True();
}

While running the debugger, I set breakpoints in the test event handler and in testObject's event handler, and I can see that the test handler fires first, then the handler I'm trying to test begins, and then the test fails before the real handler completes.

How should I change this setup so that the handler in my test will not be called until after all other handlers have been called? I'm using Visual Studio 2013, .NET 4.0 Client, NUnit 2.6.3, and Should.Fluent 1.0.

This question is somewhat similar to this previous one, except that here I want to guarantee that all other event handlers have completed first.

Edit:

Thanks to a few helpful comments, I went back to my code and realized that the problem was in my test setup. This was my original setup code:

[SetUp]
public void SetupDeviceController()
{
    dev = new TestDevice();
    dc = new DeviceController(dev);
    dev.Read += dev_Read;
    dc.Open();
}

A matching dev.Read -= dev_Read; appears in the [TearDown] method.

Community
  • 1
  • 1
Austin Mullins
  • 7,307
  • 2
  • 33
  • 48
  • 1
    Use an async method using Task and await. http://msdn.microsoft.com/en-us/library/hh156528.aspx explains how to do it. – Nzall Jun 18 '14 at 13:51
  • Also from MSDN: >Visual Studio 2012 introduces a simplified approach, async programming, that leverages asynchronous support in the **.NET Framework 4.5** and the Windows Runtime. My application targets .NET 4.0 for XP support. – Austin Mullins Jun 18 '14 at 13:54
  • 1
    http://msdn.microsoft.com/en-us/library/system.iasyncresult(v=vs.100).aspx explains how to apply async programming in .net 4.0 using IAsyncResult. Async programming is not exclusive to .net 4.5, it's just a bit trickier in 4.0. – Nzall Jun 18 '14 at 14:00
  • 1
    By default events are synchronous. Unless you've explicitly coded your events to fire asynchronously you won't have to do anything to ensure your test code executes after the handlers are executed. http://stackoverflow.com/questions/7106454/are-c-sharp-events-synchronous – Aaron Carlson Jun 18 '14 at 15:38
  • Thanks for the great links. I'm confused as to why an event handler added later gets called sooner. I assumed the handlers were called synchronously, but I'm not clear on what order they are called in, or how the order could be controlled. – Austin Mullins Jun 18 '14 at 16:14

1 Answers1

1

Ok, so, I was glossing over the real source of the problem when posting my example code above. In my actual test code, I have a SetUp method that instantiates a mock dependency object, then injects the mock objects as the dependency for the real object under test. Then, I was adding my test handler to the mock object before calling the real object method that adds the real handler. This was my real setup code:

[SetUp]
public void SetupDeviceController()
{
    dev = new TestDevice();
    dc = new DeviceController(dev);
    dev.Read += dev_Read;
    dc.Open();
}

I changed it to:

[SetUp]
public void SetupDeviceController()
{
    dev = new TestDevice();
    dc = new DeviceController(dev);
    dc.Open();
    dev.Read += dev_Read;
}

Now the handlers are run in the expected order.

Austin Mullins
  • 7,307
  • 2
  • 33
  • 48