Как смоделировать Request.ServerVariables, используя MOQ для ASP.NET MVC? - PullRequest
10 голосов
/ 05 мая 2010

Я только учусь ставить модульное тестирование для моего asp.net mvc, когда узнал о макете и различных фреймворках, которые там сейчас есть.

после проверки SO я обнаружил, что MOQ, кажется, легче всего подобрать. на данный момент я застрял, пытаясь смоделировать Request.ServerVariables, так как прочитав этот пост , я понял, что лучше абстрагировать их в свойство.

как таковой:

/// <summary>
        /// Return the server port
        /// </summary>
        protected string ServerPort
        {
            get
            {
                return Request.ServerVariables.Get("SERVER_PORT");
            }
        }

Но мне трудно научиться правильно издеваться над этим. У меня есть функция ActionResult домашнего контроллера, которая собирает информацию о сервере пользователя и приступает к созданию формы для сбора информации пользователя.

я пытался использовать класс mvcmockhelpers от hanselman , но я не уверен, как его использовать.

это то, что у меня есть ...

[Test]
        public void Create_Redirects_To_ProductAdded_On_Success() 
        {

            FakeViewEngine engine = new FakeViewEngine();

            HomeController controller = new HomeController();
            controller.ViewEngine = engine;

            MvcMockHelpers.SetFakeControllerContext(controller);

            controller.Create();

            var results = controller.Create();

            var typedResults = results as RedirectToRouteResult;

            Assert.AreEqual("", typedResults.RouteValues["action"], "Wrong action");
            Assert.AreEqual("", typedResults.RouteValues["controller"], "Wrong controller");
        }

Вопросы:

  1. На данный момент я все еще обнуляюсь ошибка исключения, когда я запускаю тестовое задание. Так чего мне здесь не хватает?
  2. И если я использую mvcmockhelpers класс, как я могу еще назвать Функция request.verifyall для обеспечения все насмешки правильно настроены?

Ответы [ 2 ]

16 голосов
/ 05 мая 2010

так что в основном я вставил все ссылки и, используя эту функцию, смог заставить ее работать. я еще не использовал класс mvcmockhelpers, так как все еще пытаюсь изучить все это.

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

[Test]
public void Create_Returns_ViewResult_On_Success() 
{
  var server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
  var response = new Mock<HttpResponseBase>(MockBehavior.Strict);

  var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
  request.Setup(x => x.ApplicationPath).Returns("/");
  request.Setup(x => x.Url).Returns(new Uri("http://localhost"));
  request.Setup(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection{
    { "SERVER_NAME", "localhost" },
    { "SCRIPT_NAME", "localhost" },
    { "SERVER_PORT", "80" },
    { "HTTPS", "www.melaos.com" },
    { "REMOTE_ADDR", "127.0.0.1" },
    { "REMOTE_HOST", "127.0.0.1" }
  });

  var context = new Mock<HttpContextBase>();
  context.SetupGet(x => x.Request).Returns(request.Object);
  context.SetupGet(x => x.Response).Returns(response.Object);
  context.SetupGet(x => x.Server).Returns(server.Object);

  var controller = new HomeController();
  //MvcMockHelpers.SetFakeControllerContext(controller);
  controller.ControllerContext = new ControllerContext(context. Object, new RouteData(), controller);

  var results = controller.Create();
  Assert.IsNotNull(results);
  Assert.IsInstanceOf(typeof(ViewResult), results);
}
0 голосов
/ 27 октября 2016

Поскольку я хочу смоделировать HttpContext, а не HttpContextBase, я попытался найти способ конвертировать фиктивный объект HttpContextBase в HttpContext и обнаружил, что это невозможно.

HttpContext

Это винтажный контекст asp.net. Проблема в том, что это не имеет базового класса и не является виртуальным, и, следовательно, непригодным для тестирования (не могу посмеяться над этим). Рекомендуется не передавать его как функцию аргументы, вместо этого передайте переменные типа HttpContextBase.

HttpContextBase

Это (новинка для c # 3.5) замена HttpContext. Так как это абстрактно, теперь это насмешливо. Идея в том, что ваши функции, которые ожидать, что будет передан контекст должен ожидать получить один из них. Это конкретно реализовано HttpContextWrapper

HttpContextWrapper

Также новый в C # 3.5 - это конкретная реализация HttpContextBase. Чтобы создать один из них на обычной веб-странице, используйте новый HttpContextWrapper (HttpContext.Current).

Идея состоит в том, что для того, чтобы сделать ваш код модульно-тестируемым, вы объявляете все свои переменные и параметры функции должны быть типа HttpContextBase, и используйте каркас МОК, например, замок Виндзор, чтобы ввести его. В норме код, замок должен ввести эквивалент «нового HttpContextWrapper (HttpContext.Current) ', тогда как в тестовом коде вы чтобы получить макет HttpContextBase.

(источник: http://www.splinter.com.au/httpcontext-vs-httpcontextbase-vs-httpcontext/)

Поэтому я изменил способ вызова своего кода.

от использования HttpContext:

public static string GetIpAddress(HttpContext currentContext) {
 ...
}

Для использования HttpContextBase:

public static string GetIpAddress(HttpContextBase currentContext) {
 ...
}

И когда я использую метод, я обертываю HttpContext с HttpContextWrapper примерно так:

var ip = GeneralUtil.GetIpAddress(new HttpContextWrapper(HttpContext.Current));

Теперь вы можете легко высмеивать HttpContextBase , следуя ответу Дана Аткинсона

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...