如何模拟或伪造HttpApplication/HttpContext进行测试

Keh*_*mme 9 c# integration-testing moq httpcontext asp.net-mvc-4

我正在尝试在我的MVC应用程序上运行一些测试,但是我一直在经历一个让它运行起来的世界.我会尽力做到这一点:

我正在使用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;
Run Code Online (Sandbox Code Playgroud)

这是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;
}
Run Code Online (Sandbox Code Playgroud)

我真的需要访问,HttpContextBase.Request.AppRelativeCurrentExecutionFilePath但它总是返回null.同样的道理HttpContext.Current.Request.RequestContext.

有人可以帮帮我吗?可以肯定地说,我现在绝望了.

Jun*_*Lee 1

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

针对您的实际问题,FakeHttpContext()尝试改变

 HttpRequestBase request = mocks.PartialMock<HttpRequestBase>();
Run Code Online (Sandbox Code Playgroud)

 HttpRequestBase request = mocks.GenerateStub<HttpRequestBase>();
Run Code Online (Sandbox Code Playgroud)

然后在你的测试中你可以这样做:

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

我认为对 HttpContext 进行部分模拟并不是很有用,因为您将测试框架(即测试框架是否根据 HttpContext 中的值 Y 和 Z 返回正确的值 X)

另一种选择是围绕 HttpContextBase 创建一个包装类,它将返回计算值。例如HttpContextBaseWrapper.AppRelativeCurrentExecutionFilePath()HttpContextBaseWrapper.RequestIpAddress()。这将使测试所有其他类变得不那么复杂,因为它们不必担心模拟 HttpContextBase 和细节,它们只需模拟您的 HttpContextBaseWrapper 类。

编辑:

我还建议您也注入 HttpRequestContext,但如果不可能,那么您可以在方法中像这样存根 RequestContext FakeHttpContext

var requestContext = MockRepository.GenerateStub<RequestContext>();
request.RequestContext = requestContext;
Run Code Online (Sandbox Code Playgroud)