Click here to Skip to main content
15,895,656 members
Articles / DevOps / Unit Testing
Tip/Trick

Mocking Event Handlers

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
19 May 2013CPOL2 min read 25K   5  
A solution for monitoring Events called during test.

Introduction

Unit testing is gaining followers in the developer community. The ability to run tests on your code in a fast and reliable form, costing almost nothing to run over and over, is very easy to justify in the long run. Unit tests are code methods that run specific portions of the production code, typically a single method every time, while ensuring to execute as many possible angles of the tested code, by setting up the input and initial state, and then validating the output and end state are as expected. Several scenarios are run one after the other to test a specific method in multiple scenarios.

There are many mocking frameworks and solutions are out there, such as NUnit, Moq, RhinoMock, and many others.

Background

Let's have a look at the following class we want to test:

C#
public class StateMachine<T>
{ 
    T _currentState;
    public void SetState(T newState)
    {
        if (newState.Equals(_currentState) || newState.Equals(default(T)))
        {
            return;
        }
        fireLeaveStatEvent(_currentState);
        fireEnterStatEvent(newState);
        _currentState = newState;
    }
    public T CurrentState
    {
        get
        {
            if (_currentState == null)
            {
                return default(T);
            }
            return _currentState;
        }
    }
    public event Action<StateMachine<T>, T> LeaveState;
    protected virtual void fireLeaveStatEvent(T oldState)
    {
        Action<StateMachine<T>, T> handler = null;
        handler = LeaveState;
        if (handler == null || oldState == null)
        { return; }
        handler(this, oldState);
    }
    /// <summary>
    /// Event raised after the Text property value has changed.
    /// </summary>
    public event Action<StateMachine<T>, T> EnterState;
    protected virtual void fireEnterStatEvent(T newState)
    {
        Action<StateMachine<T>, T> handler = null;
        handler = EnterState;
        if (handler == null || newState == null)
        { return; }
        handler(this, newState);
    }
}  

Let's start writing tests for this class. At first, we can write up a basic test scenario to test set state value:

C#
[test]
public void TestMethod
{
 var target = new TestStateMachine();
 target.SetState(1);
 int current = target.CurrentState;
 Assert.AreEqual(1, current ); 
} 

After this, we should write up other scenarios to cover special cases, like setting the same value, or a null state.

But what about monitoring the events fired by the StateMachine? I've read many discussions on firing events from mocks, but few on the other side.

One approach asks that you create your own custom delegate:

C#
[test]
public void TestMethod
{
  bool called = false;
  var target = new TestStateMachine();
  target.EnterEvent += (x,y) => called = true;
  target.SetState(1);
  Assert.AreEqual(true, called ); 
} 

This is fairly easy to do once, but is not very reusable. In general, we want our test code to run and monitor the code as it is written and not be too aware of any implementation details although it should say that there are some exceptions to this rule.

Having said that, one could suggest that we refactor the StateMachine class to take a subscriber Interface, and then pass on a Mock object that contains one form of call monitoring/enforcing or another. But this would force us never to use Events. So that stays a bad idea.

[I saw an interesting approach here and I was inspired.]

Using the Code

This is where the MockEventSubscriber comes in and saves the day. The version here is a very basic implementation, but it will be obviously easy to expand.

C#
public class MockEventSubscriber
{
    public MockEventSubscriber()
    {
        Reset();
    }
    public void Reset()
    {
        _count = 0;
    }
    public void Handle()
    {
        _count++;
    }
    public void Handle<T>(T t)
    {
        _count++;
    }
    public void Handle<T, U>(T t, U u)
    {
        _count++;
    }
    public int HitCount
    {
        get
        {
            return _count;
        }
    }
    int _count;
}

This class will monitor calls to its methods. Every call to one of its methods is recorded in the hit counter. Since all of the Handle methods take generic parameters, the delegate signature is automatically matched to any method with 0-2 parameters. Now we can use it in a Test as such:

C#
[test]
public void TestMethod
{
   var target = new TestStateMachine();
   var subscriber = new MockEventSubscriber();
   //signature will match Action<StateMachine<int>,int>
   target.LeaveState += subscriber.Handle;
   //signature will match Action<StateMachine<int>,int>
   target.EnterState += subscriber.Handle;
   target.SetState(1);
   //should this test fail?
   Assert.AreEqual(0, subscriber.HitCount);
} 

This implementation can be enhanced, for example to monitor order across multiple events. But this already enables to us to Assert the number of calls as expected.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Israel Israel
I've been developing in C# for over 7 years.
Always in some unique corner or another.

Comments and Discussions

 
-- There are no messages in this forum --