I'm implementing an IHttpModule and am trying to write unit tests for it (using NUnit and Moq). I'm having a problem mocking the HttpApplication dependency for the Init method:
void Init(HttpApplication context);
Normally, ASP.NET controls the HttpApplication instance and passes it to the Init method. In the Init method, the custom IHttpModule subscribes to events published by the HttpApplication instance (like BeginRequest and EndRequest).
I need some way to mock the HttpApplication so I can raise the events and test that my implementation of the IHttpModule event handlers work.
I've tried creating a Mock HttpApplication in my test:
// Mock for the logging dependency
var mockLogger = new Mock<ILogger>();
// My attempt at mocking the HttpApplication
var mockApplication = new Mock<HttpApplication>();
// MyModule is my class that implements IHttpModule
var myModule = new MyModule(mockLogger.Object);
// Calling Init, which subscribes my event handlers to the HttpApplication events
myModule.Init(mockApplication.Object);
// Attempting to raise the begin and end request events
mockApplication.Raise(a => a.BeginRequest += null, EventArgs.Empty);
mockApplication.Raise(a => a.EndRequest += null, EventArgs.Empty);
// RequestTime is a long property that tracks the time it took (in miliseconds) for a
// request to be processed and is set in the event handler subscribed to EndRequest
Assert.Greater(myModule.RequestTime, 0);
...but it gives the following error message:
Expression is not an event attach or detach, or the event is declared in a class but not marked virtual.
When I looked into that error, I learned that Moq can only mock Interfaces and virtual methods... So how can I mock a concrete class that I have no control over?
Here is the MyModule class:
public class MyModule : IHttpModule
{
ILogger _logger;
public long RequestTime { get; private set; }
Stopwatch _stopwatch;
public MyModule(ILogger logger)
{
_logger = logger;
}
public void Init(HttpApplication context)
{
context.BeginRequest += OnBeginRequest;
context.EndRequest += OnEndRequest;
}
public void Dispose() { }
void OnBeginRequest(object sender, EventArgs e)
{
_stopwatch = Stopwatch.StartNew();
}
void OnEndRequest(object sender, EventArgs e)
{
_stopwatch.Stop();
RequestTime = _stopwatch.ElapsedMilliseconds;
}
}
I don't think it's normally recommended, but you can use Reflection to mock non public/virtual members.
For current implementation, like this