【发布时间】:2019-03-30 01:45:18
【问题描述】:
我正在实现IHttpModule 并尝试为它编写单元测试(使用 NUnit 和 Moq)。我在模拟 Init 方法的 HttpApplication 依赖项时遇到问题:
void Init(HttpApplication context);
通常,ASP.NET 控制HttpApplication 实例并将其传递给Init 方法。在Init 方法中,自定义IHttpModule 订阅HttpApplication 实例发布的事件(如BeginRequest 和EndRequest)。
我需要一些方法来模拟 HttpApplication,以便我可以引发事件并测试我的 IHttpModule 事件处理程序的实现是否有效。
我尝试在我的测试中创建一个 Mock HttpApplication:
// 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);
...但它给出了以下错误消息:
表达式不是事件附加或分离,或者事件在类中声明但未标记为虚拟。
当我查看该错误时,我了解到 Moq 只能模拟接口和虚拟方法... 那么我如何模拟一个我无法控制的具体类?
这是MyModule 类:
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;
}
}
【问题讨论】:
-
您可以尝试使用基于界面的解决方法。
-
@cdev 感谢您的回复,但我很难理解您的意思。你能更详细地解释一下吗?或者举个例子?
-
将使用 HttpApplication 的方法移动到类和接口中,您可以将该类模拟为预期的行为。其实我更喜欢这种场景下的集成测试。
-
@cdev 我仍然不明白你的意思。
HttpApplication是 Microsoft 在System.Web中的一个类。我不能让它继承一个新的接口或改变HttpApplication。 -
我想知道没有人建议编写集成测试。单元测试有很好的特性——如果你很难编写测试。架构不是为单元测试而设计的,如果你不能重新设计并且仍然想自动测试它 - 使用集成测试,它将覆盖你应用程序的整个管道。
标签: c# unit-testing nunit moq ihttpmodule