2012-02-27 161 views
4

從在MVC3應用帳戶控制標準的登錄方法,我怎麼能測試單元測試Url.IsLocalUrl(returnUrl.ToString()),我怎麼能得到它在單元測試中返回false?

Url.IsLocalUrl(returnUrl.ToString()) 

行代碼,其中的網址是不是本地的?換句話說,當單元測試時,我需要將哪些網址送入此代碼行,才能讓它返回false?

我用下面想這將返回假(非本地):

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

,但它只是扔在單位空異常測試

編輯:我要補充的是,登錄方法現在看起來是這樣的:

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參數改變,但它是非常相似的TH一些風格COP /代碼分析錯誤e標準原件。

只是爲了澄清,在單元測試 - 我想測試並斷言擊中Else行,其中它重定向到Home/Index的結果,所以我需要傳遞的東西進入(System.Uri)returnUrl,這將使它在Url.IsLocalUrl返回false而不是拋出一個異常

進一步編輯:

我使用MvcContrib testhelper,這是在嘲諷了很多的HttpContext和網絡的東西還不錯:

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

回答

15

您需要模擬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)子句。


UPDATE:

看來你正在使用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

對不起達林我應該還補充說我使用MvcContrib TestHelper,見上編輯。相當新,但我認爲它涵蓋了很多嘲諷問題..? – DevDave 2012-02-27 10:50:55

+0

@泰勒,的確,你應該在你的問題中提到這一點。我已經更新了我的答案,以提供如何使用MvcContrib.TestHelper來實現這一目標的示例。 – 2012-02-27 10:56:49

+0

@Tyler,'new Uri(「google.co。uk「)'是一個無效的uri,它會拋出'UriFormatException'。你需要指定協議。 – 2012-02-27 11:47:07