Mocking System.Web.TraceContext with Moq
本文关键字:with Moq TraceContext Web System Mocking | 更新日期: 2023-09-27 18:03:29
我有一些代码正在访问HttpContextBase.Trace
对象并使用它做一些事情(检查IsEnabled
,写一些消息)。问题是它是一个System.Web.TraceContext
对象。TraceContext是一个只有一个构造函数的密封类:它接受一个HttpContext
对象。Moq无法模拟TraceContext
或HttpContext
。我可以在这里做些什么来测试这个代码与Moq?
或者我需要将此代码提取出来并停止引用HttpContextBase.Trace
?
我有点讨厌说"不要那样做"的答案,因为答案中可能有价值,不管采用什么方法,但是,我们开始:
别那样做。
让我们假设你有这样一个类:
public class MyCode
{
public void Do()
{
HttpContext.Current.Trace.WriteLine("WOO!");
}
}
这种事情不是很可测试的。如果您想要重构可测试性,您可以使用更多的"控制反转"类型的方法。这里我将使用"依赖注入"(还有其他选项,如"服务位置"answers"抽象工厂",但这是最容易理解的):
public class MyCode
{
private IMyLogger _logger = null;
public MyCode(IMyLogger logger)
{
_logger = logger;
}
public void Do()
{
_logger.TraceWriteLine("WOO!");
}
}
现在你可以看到,这段代码是非常可测试的,你不需要跳圈去模拟任何东西。
//Confirms "Do" method calls "TraceWriteLine"
public void Do_Called_CallsTraceWriteLine()
{
//Arrange
var loggerMock = new Mock<IMyLogger>();
loggerMock.Setup(l => l.TraceWriteLine(It.IsAny<string.());
var target = new MyCode(loggerMock.Object);
//Act
target.Do();
//Assert
loggerMock.VerifyAll();
}
现在你的IMyLogger的实现可能会调用HttpContext,但它保持你的目标类是可测试的。public DefaultLogger : IMyLogger
{
public void TraceWriteLine(string message)
{
HttpContext.Current.Trace.WriteLine(message);
}
}
为了实现这样的事情,许多人选择使用控制反转容器。您不必这样做,但它会使事情变得简单一些,并且在添加更多依赖项时不会降低可维护性。可以想象,如果. net框架的每个部分都有一个不可测试的接口,那么"new MyCode"构造函数调用将开始变得相当长。IoC容器可以帮助您避免这种情况。
流行的。net IoC容器:
- Ninject 统一
- MEF(内置到。net 4.0)
- Autofac 温莎城堡
- StructureMap
你的文章被标记为"ASP.NET"。希望你正在使用MVC。如果是这样,它将支持新的依赖注入,示例如下:http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx
希望这有帮助。对不起,它没有直接回答你的问题。