Как издеваться над HttpContext в ASP.NET MVC с помощью Moq?

[TestMethod]
public void Home_Message_Display_Unknown_User_when_coockie_does_not_exist()
{
    var context = new Mock<HttpContextBase>();
    var request = new Mock<HttpRequestBase>();
    context
        .Setup(c => c.Request)
        .Returns(request.Object);
    HomeController controller = new HomeController();

    controller.HttpContext = context; //Here I am getting an error (read only).
    ...
 }

у моего базового контроллера есть переопределение Initialize, которое получает this requestContext. Я пытаюсь передать это, но что-то делаю неправильно.

protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
    base.Initialize(requestContext);
}

Где я могу получить дополнительную информацию о имитации моего RequestContext и HttpContext с помощью Moq? Я пытаюсь имитировать файлы cookie и общий контекст.


person Geo    schedule 21.09.2009    source источник


Ответы (5)


HttpContext доступен только для чтения, но фактически является производным от ControllerContext, который вы можете установить.

 controller.ControllerContext = new ControllerContext( context.Object, new RouteData(), controller );
person tvanfosson    schedule 21.09.2009
comment
Этот сработал для меня, позволив мне установить фиктивный HttpContext на контроллере. - person Joel Malone; 14.05.2012

Создайте запрос, ответ и поместите их в HttpContext:

HttpRequest httpRequest = new HttpRequest("", "http://mySomething/", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
person 0100110010101    schedule 21.09.2009
comment
Вопрос касается * базовых классов, то есть HttpRequestBase, а не HttpRequest - я не уверен, зачем оба нужны мне, и еще больше раздражает то, что они запечатаны. Нет возможности установить LogonUserIdentity :( - person Chris Kimpton; 22.10.2010
comment
Если они упорядочили мою ссылку, это все еще возможно через удаленное взаимодействие, так что это не должно быть проблемой. - person 0100110010101; 22.10.2010
comment
@ChrisKimpton: В крайнем случае, всегда есть отражение ;-) - person Oliver; 15.01.2014
comment
Это работает при подключении его к контроллеру, например: controller.ControllerContext = new ControllerContext (новый HttpContextWrapper (httpContextMock), new RouteData (), контроллер); - person Andreas Vendel; 25.06.2014
comment
да. вы действительно можете установить .LogonUserIdentity - _request.Setup (n = ›n.LogonUserIdentity) .Returns ((WindowsIdentity.GetCurrent)); - person KevinDeus; 17.10.2014

Спасибо пользователю 0100110010101.

Это сработало для меня, и здесь у меня возникла проблема при написании тестового примера для приведенного ниже кода:

 var currentUrl = Request.Url.AbsoluteUri;

А вот строчки, которые решили проблему

HomeController controller = new HomeController();
//Mock Request.Url.AbsoluteUri 
HttpRequest httpRequest = new HttpRequest("", "http://mySomething", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
controller.ControllerContext = new ControllerContext(new HttpContextWrapper(httpContextMock), new RouteData(), controller);

Может быть полезно для других.

person Chandan Kumar    schedule 30.06.2015
comment
Кажется, я не могу использовать тип HttpRequest - это что-то еще? - person Vincent Buscarello; 11.07.2018
comment
Это бесполезно, потому что все поля в HttpRequest неизменяемы. - person A X; 08.07.2019

Вот как я использовал ControllerContext для передачи поддельного пути к приложению:

[TestClass]
public class ClassTest
{
    private Mock<ControllerContext> mockControllerContext;
    private HomeController sut;

    [TestInitialize]
    public void TestInitialize()
    {
        mockControllerContext = new Mock<ControllerContext>();
        sut = new HomeController();
    }
    [TestCleanup]
    public void TestCleanup()
    {
        sut.Dispose();
        mockControllerContext = null;
    }
    [TestMethod]
    public void Index_Should_Return_Default_View()
    {

        // Expectations
        mockControllerContext.SetupGet(x => x.HttpContext.Request.ApplicationPath)
            .Returns("/foo.com");
        sut.ControllerContext = mockControllerContext.Object;

        // Act
        var failure = sut.Index();

        // Assert
        Assert.IsInstanceOfType(failure, typeof(ViewResult), "Index() did not return expected ViewResult.");
    }
}
person Xolartek    schedule 27.10.2011
comment
Зачем нужно было передавать поддельный путь к приложению? - person the_law; 10.11.2011
comment
Код MVC выполнит его и выдаст нулевое исключение, если его нет. - person Joshua Ramirez; 15.01.2013

Вот пример того, как вы можете это настроить: Mocking HttpContext HttpRequest и HttpResponse для UnitTests (с использованием Moq)

Обратите внимание на методы расширения, которые действительно помогают упростить использование этих насмешливых классов:

var mockHttpContext = new API_Moq_HttpContext();

var httpContext = mockHttpContext.httpContext();

httpContext.request_Write("<html><body>".line()); 
httpContext.request_Write("   this is a web page".line());  
httpContext.request_Write("</body></html>"); 

return httpContext.request_Read();

Вот пример того, как написать модульный тест с использованием moq, чтобы проверить, что HttpModule работает должным образом: Модульный тест для HttpModule с использованием Moq для обертывания HttpRequest

Обновление: этот API был изменен на

person Dinis Cruz    schedule 10.04.2011
comment
Ссылки не работают - укажите код в своем ответе - person Hades; 06.01.2020