簡體   English   中英

在常規mvc控制器中使用標識的單元測試方法(不是web api控制器)

[英]unit test method that uses identity in regular mvc controller (not web api controller)

我在常規mvc控制器中有一個方法,它檢查用戶的身份以查看用戶應該指向哪個頁面。 但是,針對此方法構建單元測試會引發“對象引用未設置”錯誤,因為當方法作為測試的一部分運行時,User始終為null。

public ActionResult Index()
        {
            if (User.Identity.IsAuthenticated)
            {
                if (User.IsInRole("Administrator"))
                {
                    return RedirectToAction("Console");
                }

                ViewBag.StatusMessage = "You are logged in but do not have sufficient permissions.";
            }
            else
            {
                ViewBag.StatusMessage = "Please log in";
            }

            return View();
        }

我已經嘗試過在Writing Unit Test中為ASP.NET Web API中使用User.Identity.Name的方法提供的各種解決方案。 這些通常在單元測試的主體內使用類似下面的內容:

var identity = new GenericIdentity("UserName");
Thread.CurrentPrincipal = new GenericPrincipal(identity, null);
var controller = new FooController(); 

如果Controller是ApiController,這種方法可以正常工作 - 即WebApi項目的控制器,但它似乎不適用於常規的Web mvc控制器。 User對象保持為null。 怎么解決?

您發布的這個鏈接與WebAPI有關,可以理解的是單元測試ApiController並訪問User對象非常容易。

這是與ASP.NET MVC不同的一些,因為您已經看到它並不簡單。 如果我們走下使用手動/手寫模擬的道路,我們可能會發現我們自己嘲笑整個宇宙,反對寫一個有價值的測試。

我包含了這兩種方法,因此您可以了解這個想法。 我也使用了問題中發布的鏈接中的相同示例。

使用手動手寫的模擬

//System Under Test - i.e to test User
public class SutController : Controller
{
    public string Get() {
        return User.Identity.Name;
    }
}

public class TestableControllerContext : ControllerContext {
    public TestableHttpContext TestableHttpContext { get; set; }
}

public class TestableHttpContext : HttpContextBase {
    public override IPrincipal User { get; set; }
}

[TestMethod]
public void IndexNoneMoq()
{
    var identity = new GenericIdentity("tugberk");
    var controller = new SutController();

    var controllerContext = new TestableControllerContext();
    var principal = new GenericPrincipal(identity, null);
    var testableHttpContext = new TestableHttpContext
    {
        User = principal
    };

    controllerContext.HttpContext = testableHttpContext;
    controller.ControllerContext = controllerContext;

    Assert.AreEqual(controller.Get(), identity.Name);
}

使用Mocking / Isolation框架即Moq

[TestMethod]
public void IndexMoq()
{
    var identity = new GenericIdentity("tugberk");          
    var controller = new SutController();

    var controllerContext = new Mock<ControllerContext>();
    var principal = new Mock<IPrincipal>();
    principal.Setup(p => p.IsInRole("Administrator")).Returns(true);
    principal.SetupGet(x => x.Identity.Name).Returns("tugberk");
    controllerContext.SetupGet(x => x.HttpContext.User).Returns(principal.Object);
    controller.ControllerContext = controllerContext.Object;

    Assert.AreEqual(controller.Get(), identity.Name);
}

請注意,我認為下一版本的ASP.NET對WebAPI和MVC(AFAIK)使用相同的底層組件,因此這可能是單向測試使用User實例的目標控制器。

這是您可以在MVC單元測試控制器中編寫的手動模擬。

[TestMethod]
public void IndexManualMoq()
{
.
.
.
    var controller = new SutController();
    controller.ControllerContext = new ControllerContext
    {
        HttpContext = new MockHttpContext
        {
            User = new GenericPrincipal(new GenericIdentity("JDoe"), null)
        }
    };
.
.
.
}

private class MockHttpContext : HttpContextBase
{
    public override IPrincipal User { get; set; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM