2013-12-13 28 views
9

我试图在我的MVC应用程序上运行一些测试,但我一直在经历一个让它工作的麻烦世界。我会尽量得到正确的一点是:如何嘲笑或伪造HttpApplication/HttpContext进行测试

我使用RhinoMocks尝试这样的事:

设置:

MockRepository mocks = new MockRepository(); 
HttpContextBase _mockContext = mocks.FakeHttpContext(); 
mocks.SetFakeControllerContext(new LoginController()); 
HttpApplicationStateBase appState = MockRepository.GenerateStub<HttpApplicationStateBase>(); 
_mockContext.Expect(mc => mc.Application).Return(appState); 
HttpContext.Current = _mockContext.ApplicationInstance.Context; 

这里的FakeHttpContext()方法:

public static HttpContextBase FakeHttpContext(this MockRepository mocks) 
{ 
    HttpApplication app = mocks.PartialMock<HttpApplication>(); 

    HttpContextBase context = mocks.PartialMock<HttpContextBase>(); 
    HttpRequestBase request = mocks.PartialMock<HttpRequestBase>(); 
    HttpResponseBase response = mocks.PartialMock<HttpResponseBase>(); 
    HttpSessionStateBase session = mocks.PartialMock<HttpSessionStateBase>(); 
    HttpServerUtilityBase server = mocks.PartialMock<HttpServerUtilityBase>(); 

    SetupResult.For(context.ApplicationInstance).Return(app); 

    SetupResult.For(context.Request).Return(request); 
    SetupResult.For(context.Response).Return(response); 
    SetupResult.For(context.Session).Return(session); 
    SetupResult.For(context.Server).Return(server); 

    mocks.Replay(context); 
    return context; 
} 

我真的需要访问HttpContextBase.Request.AppRelativeCurrentExecutionFilePath,但它总是以null的形式返回。 HttpContext.Current.Request.RequestContext也是如此。

有人可以帮我吗?可以肯定的是,我现在绝望了。

+0

你不要告诉问题是什么?你有错误(哪一个?)?据我所见,特定的设置'安装程序(c => c.Request。AppRelativeCurrentExecutionFilePath)'应该可以工作,因为'Request'是一个'virtual'属性'AppRelativeCurrentExecutionFilePath'的'virtual'属性。你说'_mockContext.SetupAllProperties();'的原因是什么?您还希望设置其他*属性? –

+0

@JeppeStigNielsen我更新了我现在使用的问题。我仍然无法工作。 – Kehlan

回答

1

首先,请尽量避免使用HttpContext.Current,因为使用静态方法会使您现在发现的测试变得更加困难。如果您正在使用依赖注入框架,请将HttpContextBase注入到构造函数中。

为您的实际问题,在FakeHttpContext()试图改变

HttpRequestBase request = mocks.PartialMock<HttpRequestBase>(); 

HttpRequestBase request = mocks.GenerateStub<HttpRequestBase>(); 

,然后在您的测试,你可以做这样的事情:

_mockContext.Request.Stub(x=> x.AppRelativeCurrentExecutionFilePath).Return("foo"); 
var result = object.DoSomething(); 
Assert.AreEqual("foo",result); 

我不认为在HttpContext上进行部分模拟是非常有用的,因为您将测试fra代替作业(即测试框架根据HttpContext中的值Y和Z返回正确值X)

另一种方法是创建一个围绕HttpContextBase的包装类,它将返回计算值。例如。 HttpContextBaseWrapper.AppRelativeCurrentExecutionFilePath(),HttpContextBaseWrapper.RequestIpAddress()。这将使得测试所有其他类更加简单,因为它们不必担心模拟HttpContextBase和细节,而只需模拟HttpContextBaseWrapper类。

编辑:

我也建议你注入你的HttpRequestContext为好,但如果这是不可能的,那么你可以存根的RequestContext像这样在FakeHttpContext方法:

var requestContext = MockRepository.GenerateStub<RequestContext>(); 
request.RequestContext = requestContext; 
+0

我真的很感激这个答案。我编辑了OP,因为我遇到了另一个问题。我还需要模拟'HttpContext.Current.Request.RequestContext'。你有什么机会帮助我呢? – Kehlan

+0

我已更新我的答案,以允许您存根RequestContext。 –

+0

我不太清楚'HttpRequestContext'是什么。我假设你的意思是'RequestContext'。再次感谢!我会试试看看它是如何发展的。 – Kehlan

1

为什么不制作一个包含对HttpContext库的调用的抽象类?

然后,你可以做这样的事情:

public class MyClass 
{ 
    private readonly IHttpContext _httpContext; 
    MyClass(IHttpContext httpContext) 
    { 
     _httpContext = httpContext; 
    } 

    public void Blaat() 
    { 
     _httpContext.DoYourThingsWithTheHttpContext(); 
    } 
} 

假设你正在使用依赖注入,否则看微软的假动作和存根框架。