7

我是 Mocking 框架的新手,并且已经开始使用 RhinoMocks 来协助我的 MVC 应用程序单元测试。

我正在使用Scott Hanselmanns MVC Mock Helper来协助模拟 HttpContext。我已经成功地(一段时间后)模拟了一些我需要的东西,但是在涉及到 HttpContext 的 Application 属性时却没有解决问题。

在我的应用程序中,我将一个对象存储在应用程序中并在控制器中检索它,例如:

SomeObj foo = (SomeObj)Application["fooKey"];

这是在我的 MVC 应用程序中的 Application_Start 上创建的。

更新以下第一个答案(为清楚起见附加代码)目前在测试设置中我做:

HttpContextBase mockHttpBase = mocks.FakeHttpContext();
controllerToTest = new SomeController();
mocks.SetFakeControllerContext(controllerToTest);


HttpApplicationStateBase appState = 
    MockRepository.GenerateStub<HttpApplicationStateBase>();

Globals tmpAppGlobals = 
    new Globals();

mockHttpBase.Expect(ctx => ctx.Application).Return(appState);
mockHttpBase.Expect(ctx => ctx.Application[Globals.GlobalsKey]).
    Return(tmpAppGlobals);

在我的单元测试设置中,我这样做:

Globals tmpAppGlobals = new Globals();
controllerToTest.ControllerContext.HttpContext.
            Expect(ctx => ctx.Application[Globals.GlobalsKey]).
Return(tmpAppGlobals);

此调用为 Application 对象引发 NullReference 异常。

我的问题有两个:

1)这是正确的方法还是我从设计/架构的角度做错了什么?

2)为什么这不起作用?!

提前致谢。

4

2 回答 2

1

无需深入研究,这看起来大多是正确的。

Application 属性在 HttpContextBase 上是虚拟的,因此您应该能够从 Rhino 为它设置一个返回值——假设您像 Scott Hanselmanns 的帖子那样模拟 HttpContextBase。

一些可能的原因,实际上只是缺乏信息的猜测:

  • 您是否为 controllerToTest.ControllerContext 设置了返回?
  • 您是否为该 对象的 HttpContext 属性设置了返回值?
  • 您是否为该 对象的应用程序属性设置了返回?

我问的原因是,通常当您进行期望设置时,您已经拥有对将作为测试的一部分调用的对象的引用,因此您不会像controllerToTest.ControllerContext.HttpContext. Expect()调用时那样执行属性链。

编辑:

我想我看到了问题,我认为这与这部分有关:

Expect(ctx => ctx.Application[Globals.GlobalsKey])

我认为您假设索引器的工作方式与属性相同,但实际上它们并非如此。您真正需要做的是在您的appState对象上设置一个期望以接收对 Item 属性的调用,如下所示:

// setup expectations -- assumes some of the expectations and mocks 
// the from original question
mockHttpBase.Expect(ctx => ctx.Application).Return(appState);
appState.Expect(ctx => ctx.Item(Globals.GlobalsKey)).Return(tmpAppGlobals);

// run the test
于 2009-04-01T15:06:58.000 回答
1

您可以将以下内容用于最小起订量。我花了一段时间来模拟 HttpApplication,而 appState.Object 是返回方法,呵呵!

public static HttpContextBase FakeHttpContext()
    {
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new FakeHttpSessionState();
        var server = new Mock<HttpServerUtilityBase>();
        var appState = new Mock<HttpApplicationStateBase>();

        context.Setup(ctx => ctx.Request).Returns(request.Object);
        context.Setup(ctx => ctx.Response).Returns(response.Object);
        context.Setup(ctx => ctx.Session).Returns(session);
        context.Setup(ctx => ctx.Server).Returns(server.Object);
        context.Setup(ctx => ctx.Application).Returns(appState.Object);

        //emulate session (HttpContext.Current.Session) 
        var contx = new HttpContext(new MyApp.NUnit.Tests.Fakes.FakeHttpWorkerRequest());
        contx.Items["AspSession"] = CreateSession();

        HttpContext.Current = contx;

        return context.Object;
    }
于 2010-08-16T22:04:01.277 回答