Как использовать Rhino Mocks для насмешки HttpContext.Application - PullRequest
7 голосов
/ 01 апреля 2009

Я новичок в платформах Mocking и начал использовать RhinoMocks для помощи в модульном тестировании приложений MVC.

Я использую Scott Hanselmanns MVC Mock Helper , чтобы помочь в насмешке над HttpContext. Я успешно (через некоторое время) высмеял кое-что из того, что мне нужно, но отклеился, когда дело доходит до свойства Application в HttpContext.

В моем приложении я сохраняю объект в приложении и извлекаю его в контроллере, например:

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

Это создается в Application_Start в моем приложении MVC.

ОБНОВЛЕНО СЛЕДУЮЩИМ ПЕРВЫМ ОТВЕТОМ (дополнительный код для ясности) В настоящее время в настройках теста я делаю:

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);

Этот вызов вызывает исключение NullReference для объекта Application.

У меня вопрос в два раза:

1) Это правильный подход или я сделал что-то не так с точки зрения дизайна / архитектуры?

2) Почему это не работает?!

Спасибо, заранее.

Ответы [ 2 ]

1 голос
/ 17 августа 2010

вы можете использовать ниже для Moq. Мне потребовалось некоторое время, чтобы посмеяться над HttpApplication, и appState.Object - это метод возврата duh!

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;
    }
1 голос
/ 01 апреля 2009

Не углубляясь слишком глубоко, это выглядит в основном правильно.

Свойство Application является виртуальным в HttpContextBase, поэтому вы должны иметь возможность установить для него возвращаемое значение из Rhino - при условии, что вы издеваетесь над 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
...