How can I unit test unsubscribing from an event? (C#)

I’ve seen some strange bugs that occur when you don’t properly unsubscribe from events. But it seems I’m always stuck when it comes to unit testing that.

Well, I use Moq for most of my mocking and there are some techniques you can use for testing that your subscribed, namely by Raise(ing) the event in a mock.

But I always struggle when trying to see if I actually unsubscribe in my code. Here is a simple sample that shows how you can do it with very little code.

Here is all the code:

Code Snippet
  1. public interface IHasEvents
  2. {
  3.     event EventHandler BeginRequest;
  4. }
  5.  
  6. public class ClassUnderTest
  7. {
  8.     internal IHasEvents ClassWithEvents { get; set; }
  9.     public ClassUnderTest(IHasEvents classWithEvents)
  10.     {
  11.         ClassWithEvents = classWithEvents;
  12.         ClassWithEvents.BeginRequest += OnBeginRequest;
  13.     }
  14.     public void Dispose()
  15.     {
  16.         // Yes… there are code analysis warnings here… But I want to keep simple.
  17.         ClassWithEvents.BeginRequest -= OnBeginRequest;
  18.     }
  19.  
  20.     public void OnBeginRequest(object sender, EventArgs e) { }
  21. }
  22.  
  23. public class MockHasEvents : IHasEvents
  24. {
  25.     public int BeginRequestSubscriberCount { get; set; }
  26.     public event EventHandler BeginRequest
  27.     {
  28.         add { BeginRequestSubscriberCount++; }
  29.         remove { BeginRequestSubscriberCount–; }
  30.     }
  31. }

And here is the code that tests that the constructor subscribes and the Dispose() unsubscribes.

Code Snippet
  1. [TestClass]
  2. public class ExampleEventMockTest
  3. {
  4.     [TestMethod]
  5.     public void Constructor_Subscribes_To_BeginRequest()
  6.     {
  7.         // Arrange
  8.         var expected = 1;
  9.         var hasEvents = new MockHasEvents();
  10.  
  11.         // Act
  12.         var subject = new ClassUnderTest(hasEvents);
  13.  
  14.         // Assert
  15.         var actual = hasEvents.BeginRequestSubscriberCount;
  16.         Assert.AreEqual(expected, actual);
  17.         //actual.Should().Be(expected); // I usually use FluentAssertions.
  18.     }
  19.  
  20.     [TestMethod]
  21.     public void Dispose_Unsubscribes_From_BeginRequest()
  22.     {
  23.         // Arrange
  24.         var expected = 0;
  25.         var hasEvents = new MockHasEvents();
  26.         var subject = new ClassUnderTest(hasEvents);
  27.  
  28.         // Act
  29.         subject.Dispose();
  30.  
  31.         // Assert
  32.         var actual = hasEvents.BeginRequestSubscriberCount;
  33.         Assert.AreEqual(expected, actual);
  34.     }
  35. }

I hope this helps others.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.