Як я знущаюся над HttpContext в ASP.NET MVC за допомогою Moq?


101
[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, що отримує цей запитContext. Я намагаюся передати це разом, але я щось не роблю правильно.

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

Де я можу отримати більше інформації про знущання над моїми RequestContext та HttpContext за допомогою Moq? Я намагаюся знущатися над файлами cookie та загальним контекстом.

Відповіді:


61

HttpContext є лише для читання, але він фактично походить від ControllerContext, який ви можете встановити.

 controller.ControllerContext = new ControllerContext( context.Object, new RouteData(), controller );

Цей працював для мене, дозволяючи мені встановити макет HttpContext на контролері.
Джоел Малоун

39

Створіть запит, відповідь і поставте їх обох у HttpContext:

HttpRequest httpRequest = new HttpRequest("", "http://mySomething/", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);

Питання в тому, що стосується * базових класів, тобто HttpRequestBase, а не HttpRequest - не впевнений, чому обидва мені потрібні, і ще більше дратує те, що вони "запечатані". Жоден спосіб встановити LogonUserIdentity :(
Кріс Кімптон

Якщо вони скасують мою довідку, це все ще можливо шляхом видалення, тому це не повинно бути проблемою.
0100110010101

1
@ChrisKimpton: В крайньому випадку, завжди є роздуми ;-)
Олівер

Це працює при приєднанні його до контролера, наприклад: controller.ControllerContext = новий ControllerContext (новий HttpContextWrapper (httpContextMock), новий RouteData (), контролер);
Андреас Вендел,

так. ви дійсно можете встановити .LogonUserIdentity - _request.Setup (n => n.LogonUserIdentity) .Повернення ((WindowsIdentity.GetCurrent));
КевінДеус

12

Дякую користувачеві 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);

Може бути корисним для інших.


Я не можу використовувати тип HttpRequest - це щось інше зараз?
Вінсент Бускарелло

1
Це не корисно , тому що все поля в HttpRequest незмінні
БР

5

Ось як я використовував 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.");
    }
}

1
Чому вам потрібно було пройти підроблений шлях програми?
the_law

Код MVC виконає його і видасть нульовий виняток, якщо його немає.
Джошуа Рамірес

5

Ось приклад того, як ви можете налаштувати це: глузування 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();

Ось приклад того, як написати Unit Test за допомогою moq, щоб перевірити, чи працює HttpModule як очікується: Unit Test для HttpModule за допомогою Moq для завершення HttpRequest

Оновлення: цей API було відновлено до нього


Посилання порушені - будь ласка, включіть код у свою відповідь
Аїд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.