Модульное тестирование Url.IsLocalUrl (returnUrl.ToString ()), как мне заставить его возвращать false в модульном тесте? - PullRequest
6 голосов
/ 27 февраля 2012

Из стандартного метода LogOn в контроллере учетных записей в приложениях MVC3, как я могу проверить

Url.IsLocalUrl(returnUrl.ToString()) 

строка кода, где URL не является локальным? Другими словами, какой URL-адрес нужно указать в этой строке кода при модульном тестировании, чтобы он возвращал значение false?

Я использовал следующее предположение, что это будет возвращено как ложное (не локально):

Uri uri = new Uri(@"http://www.google.com/blahblah.html");

Но в модульных тестах он только что выдал нулевое исключение

Редактировать: я должен добавить, что метод LogOn теперь выглядит так:

public ActionResult LogOn(LogOnModel model, System.Uri returnUrl)

if (ModelState.IsValid) {

            bool loggedOn = LogOn(model);

            if (loggedOn) {
                if (Url.IsLocalUrl(returnUrl.ToString())) {
                    return Redirect(returnUrl.ToString());
                }
                else {
                    return RedirectToAction("Index", "Home");
                }
            }
            else {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }

        // If we got this far, something failed, redisplay form
        return View(viewModel);
    }

Из-за некоторых ошибок анализа кода / стиля стиль изменился с строкового параметра на параметр System.uri, но он очень похож на стандартный оригинал.

Просто чтобы уточнить, в модульном тесте - я хочу проверить и подтвердить результат попадания в строку Else, где он перенаправляет на Home/Index, поэтому мне нужно передать что-то в (System.Uri)returnUrl, что он возвращает false на Url.IsLocalUrl и не выдает исключение

Дальнейшее редактирование:

Я использую тестовый помощник MvcContrib, который неплохо умеет насмехаться над многими httpcontext и веб-материалами:

Builder = new TestControllerBuilder();
UserController = new UserController();
    Builder.InitializeController(UserController);

1 Ответ

17 голосов
/ 27 февраля 2012

Вам необходимо смоделировать HttpContext, а также экземпляр UrlHelper на контроллере, который вы тестируете модулем.Вот пример того, как может выглядеть этот модульный тест, если вы используете Moq :

[TestMethod]
public void LogOn_Should_Redirect_To_Home_If_Authentication_Succeeds_But_Not_Local_ReturnUrl_Is_Provided()
{
    // arrange
    var sut = new AccountController();
    var model = new LogOnModel();
    var returnUrl = new Uri("http://www.google.com");
    var httpContext = new Mock<HttpContextBase>();
    var request = new Mock<HttpRequestBase>();
    httpContext.Setup(x => x.Request).Returns(request.Object);
    request.Setup(x => x.Url).Returns(new Uri("http://localhost:123"));
    var requestContext = new RequestContext(httpContext.Object, new RouteData());
    sut.Url = new UrlHelper(requestContext);

    // act
    var actual = sut.LogOn(model, returnUrl);

    // assert
    Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
    var result = (RedirectToRouteResult)actual;
    Assert.AreEqual("Home", result.RouteValues["controller"]);
    Assert.AreEqual("Index", result.RouteValues["action"]);
}

Примечание: поскольку вы фактически показали реализацию LogOn, которую вы вызываете для проверкиучетные данные, вам может потребоваться адаптировать модульный тест, чтобы этот метод возвращал значение true в первую очередь, учитывая модель, чтобы ввести предложение if (loggedOn).


ОБНОВЛЕНИЕ:

Похоже, что вы используете MvcContrib.TestHelper , который выполняет все настройки макета HttpContext для вас.Таким образом, все, что вам нужно сделать, это смоделировать соответствующие части для вашего модульного теста:

[TestMethod]
public void LogOn_Should_Redirect_To_Home_If_Authentication_Succeeds_But_Not_Local_ReturnUrl_Is_Provided()
{
    // arrange
    var sut = new AccountController();
    new TestControllerBuilder().InitializeController(sut);
    var model = new LogOnModel();
    var returnUrl = new Uri("http://www.google.com");
    sut.HttpContext.Request.Expect(x => x.Url).Return(new Uri("http://localhost:123"));

    // act
    var actual = sut.LogOn(model, returnUrl);

    // assert
    actual
        .AssertActionRedirect()
        .ToController("Home")
        .ToAction("Index");
}

Обычно первые 2 строки модульного теста можно переместить в глобальный метод [SetUp], чтобы избежать их повторенияв каждом модуле теста для этого контроллера, так что теперь ваш тест становится немного чище:

[TestMethod]
public void LogOn_Should_Redirect_To_Home_If_Authentication_Succeeds_But_Not_Local_ReturnUrl_Is_Provided()
{
    // arrange
    var model = new LogOnModel();
    var returnUrl = new Uri("http://www.google.com");
    _sut.HttpContext.Request.Expect(x => x.Url).Return(new Uri("http://localhost:123"));

    // act
    var actual = _sut.LogOn(model, returnUrl);

    // assert
    actual
        .AssertActionRedirect()
        .ToController("Home")
        .ToAction("Index");
}
...