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无法模拟TraceContextHttpContext。我可以在这里做些什么来测试这个代码与Moq?

或者我需要将此代码提取出来并停止引用HttpContextBase.Trace ?

Mocking System.Web.TraceContext with Moq

我有点讨厌说"不要那样做"的答案,因为答案中可能有价值,不管采用什么方法,但是,我们开始:

别那样做。

让我们假设你有这样一个类:

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

希望这有帮助。对不起,它没有直接回答你的问题。