单元测试Url.IsLocalUrl(returnUrl.ToString()),如何在单元测试中返回false?

问题描述 投票:6回答:2

从MVC3应用程序中帐户控制器中的标准LogOn方法,如何测试

Url.IsLocalUrl(returnUrl.ToString()) 

URL所在的代码行不是本地的?换句话说,在单元测试时,我必须向该代码行输入什么url,以使其返回false?

我已经使用了以下思想,这将返回为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中以使其成功在Url.IsLocalUrl上返回false且不引发异常

进一步编辑:

我正在使用MvcContrib testhelper,它非常擅长模拟许多httpcontext和Web内容:

Builder = new TestControllerBuilder();
UserController = new UserController();
    Builder.InitializeController(UserController);
asp.net-mvc-3 url local returnurl
2个回答
17
投票

您需要在进行单元测试的控制器上模拟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");
}

通常,单元测试的前两行可以移到全局[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");
}

0
投票

我登陆这里搜索控制器中的空引用和当前答案的日期是否过时。我使用moq很好地做到了这一点:

© www.soinside.com 2019 - 2024. All rights reserved.