将Web上下文传递给ASP MVC应用程序中的“服务”

时间:2008-12-02 12:57:05

标签: c# .net asp.net-mvc tdd mocking

我正在尝试将Web当前的http上下文传递给服务类(或者通过引用它来初始化类)。我这样做是为了抽象应用程序的其余部分,而不是需要了解有关http上下文的任何信息。

我也希望使用TDD测试服务,可能使用其中一个Mockable框架。因此,最好使用接口而不是实际的类。

我想要实现的一个例子:

class WebInstanceService 
{
    private IHttpContext _Context;        

    public WebInstanceService( ... , IHttpContext HttpContext )
    {
        ....
        _Context = HttpContext;
    }

    // Methods...
    public string GetInstanceVariable(string VariableName)
    {
         return _Context.Current.Session[VariableName];
    }
}

我遇到的一个主要问题是没有IHttpContext,.net http上下文是一个抽象类的子类,不能被模拟(很容易?)。

另一个问题是我无法初始化类的全局实例,因为上下文与大多数请求无关。

我可以使类静态化,并且要求将Context传递给调用的每个函数,即

public static string GetInstanceVariable(string VariableName, HttpContext Context) 
{ ... }

但是这并没有使类更容易测试,我仍然需要创建一个HttpContext,另外任何想要使用这个类的非Web感知服务突然需要能够检索需要它们的Context。与Web服务器紧密耦合 - 首先想要创建这个类的全部原因。

我对所有建议持开放态度 - 特别是那些人们知道有助于轻松进行tdd测试的建议。 人们会如何建议我解决这个问题?

干杯

3 个答案:

答案 0 :(得分:3)

这就是引入HttpContextBase和HttpContextWrapper的原因。您可能想要使用HttpContextBase,并且在传递真实上下文时,使用new HttpContextWrapper( httpContext ),尽管如此,我认为控制器中可用的内容已经是HttpContextBase类型。我每次都会在我的控制器中创建其中一个,而不是尝试从静态的全局HttpContext.Current实例引用当前上下文。如果您在视图中需要它,请在ViewData中传递对强类型上下文的引用。

我在测试中经常模拟HttpContextBase。

class WebInstanceService 
{
    private HttpContextBase _Context;        

    public WebInstanceService( ... , HttpContextBase HttpContext )
    {
        ....
        _Context = HttpContext;
    }

    // Methods...
    public string GetInstanceVariable(string VariableName)
    {
         return _Context.Session[VariableName];
    }
}

答案 1 :(得分:1)

我们做的是将其中一个向上旋转http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx

简单易行,只需实例化一个HttpSimulator并填写值,HttpContext.Current就会被你指定的内容填满。

IHttpContext是MVC中的东西,而且有一天会出现在webforms中。希望那一天将是.net 4

答案 2 :(得分:1)

ASP.NET附带了System.Web.Abstractions,其中包含HttpContextBase,您可以在测试情况下使用它来处理HttpContext。

我个人会抽象出对HttpContext的直接依赖。