单元通过调用包装HttpContext的Static类来测试类

时间:2010-11-25 09:33:53

标签: c# unit-testing static-methods httpcontext

我有一个方法,我在C#/ ASP.Net Web项目中添加了单元测试。该方法已被其他人修改为包含对包装HttpContext的类的静态方法的调用(以添加一些会话状态),但在测试期间我没有HttpContext,因此抛出空引用异常。任何想法如何解决这个问题?如果我能提供帮助,我不想对生产代码进行太多更改。

待测方法:

public int MethodUnderTest() 
{
    ...
    // Added line which breaks the tests
    StaticClass.ClearSessionState();
}

在StaticClass中:

public void ClearSessionState()
{
    HttpContext.Current.Session["VariableName"] = null;
}

这会抛出NullReferenceException因为HttpContext.Current在测试期间为空。

4 个答案:

答案 0 :(得分:1)

就使用HttpContext.Current的单元测试方法而言,你几乎处于死胡同。正确的方法是修改此代码以使用构造函数注入:

private readonly HttpContextBase _context;
public Foo(HttpContextBase context)
{
    _context = context;
}

public void ClearSessionState()
{
    _context.Session["VariableName"] = null;
}

现在您可以在单元测试中模拟此HttpContextBase

答案 1 :(得分:1)

在调用StaticClass.ClearSessionState()行之前,可以使用mock / stub对象设置HttpContext.Current。

答案 2 :(得分:1)

您可以在生产代码中执行自己的静态“注入”,如下所示:

public static class StaticClass {
    public void ClearSession() {
        TheContext["VariableName"] = null;
    }

    public static HttpContextBase TheContext{
        get { 
            if (_context == null)
                _context = new HttpContextWrapper(HttpContext.Current);
            return _context; }
        set { _context = value; }
    }
}

然后,实际测试变得非常简单,只需在测试之前将TheContext属性设置为存根实例。例如,在Moq中,这样的存根可以设置为一行:

StaticClass.TheContext = new Mock<HttpContextBase>(){DefaultValue = DefaultValue.Mock}.Object;

答案 3 :(得分:0)

最后,我可以删除对StaticClass.ClearSessionState()的调用,但感谢所有答案。有用的东西。