Matt
Matt

Reputation: 4301

unit testing/ mocking static event handlers, what are the available options?

Im fully aware of the "problem" with static event handlers from a GC perspective so i'm not looking for advice on "DONT use static events" or anything like that, in my scenario this isnt a concern.

I have a static class which has an event declared

public static event EventHandler<MyEventArgs> FilePickedUpFromStorage;

i have a client service that subscribes to this event and im wanting to Mock/test the static event being fired with a fake MyEventArgs to assert the handling works as specified, at the client. Straightforwards stuff.... the problem i have is that this event is static on a static class. im looking for some solid guidance on the best approach to dealing with this, if anyone can offer any help. Changing the static event is not an option, wrapping it or any other magic is...

Thanks!

Upvotes: 0

Views: 950

Answers (3)

Stefan Steinegger
Stefan Steinegger

Reputation: 64628

You could keep the static event for "legacy compatibility" and provide a better structure for new (and testable) code.

// legacy
public static class OldClass
{
  public static event EventHandler<MyEventArgs> FilePickedUpFromStorage;
}

// new interface for testability
public interface IBraveNewWorld
{
  event EventHandler<MyEventArgs> FilePickedUpFromStorage;
}

// new implementation
public class BraveNewWorld : IBraveNewWorld
{
  public event EventHandler<MyEventArgs> FilePickedUpFromStorage;
  public BraveNewWorld()
  {
    // MyHandler forwards the event
    OldClass.FilePickedUpFromStorage += MyHandler;
  }
}

// new testable user of the event.
public class TestableClass
{
  // here you can pass a mock or just an instance of BraveNewWorld
  public TestableClass(IBraveNewWorld x)
  {

  }
}

Upvotes: 2

djna
djna

Reputation: 55907

You are testing your class's response to receiving an event. So presumably you are concerned about the bahviour of a method on your class which receives the event

public void OnHandler1(object sender, MyEventArgs e)

So in your tests don't you just call that method directly? You might need to mock the sender object, but presumbly he is of a known type because you're casting him to use him, so you know what to mock.

In other words for testing your class you may not actually need the real source of events at all.

Upvotes: -2

Brian Rasmussen
Brian Rasmussen

Reputation: 116401

Since you specifically states that it is not an option to change the event from static to instance, you could take a look at TypeMock Isolator. It is a mocking framework that works by rewriting IL code necessary to mock stuff that could not otherwise be mocked. It is not the best solution IMO, but it will help you do want you want in this situation without changing the code.

Upvotes: 3

Related Questions