Asp.net-Mvc-3

單元測試 Url.IsLocalUrl(returnUrl.ToString()),我怎樣才能讓它在單元測試中返回 false?

  • December 11, 2019

從 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它,這將使它返回 falseUrl.IsLocalUrl而不會引發異常

進一步編輯:

我正在使用 MvcContrib testhelper,它非常擅長模擬很​​多 httpcontext 和 web 內容:

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

您需要在您正在單元測試的控制器上模擬 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");
}

引用自:https://stackoverflow.com/questions/9463201