2

我正在尝试在 ASP MVC 控制器上运行几个基本单元测试,但是有一次控制器需要IPrincipal User像这样检查对象:

ViewBag.Level = Security.GetLevel(User);

但是,一旦单元测试进入Create控制器方法,上面的行就会抛出 a NullReferenceExceptionas the Userobject is null

关于如何设置IPrincipal单元测试会话的任何想法?

这是我现在写的测试。我试图访问该User对象并在测试进入Create方法之前简单地设置它,但是智能感知没有拾取它。

    [Test]
    public void a06_CloneFromDatabase()
    {
        using (AgentResources db = new AgentResources())
        {
            var master = (from a in db.AgentTransmission
                          where a.RecordStatus.Equals("C")
                          select a).FirstOrDefault();



            var result = _controlAgtTran.Create(master.ID, null, string.Empty, string.Empty, string.Empty, string.Empty, false) as ViewResult;
            var model = result.Model as AgentTransmission;

            Assert.AreEqual(model.ReferenceType, master.ReferenceType);
        }
    }

编辑

在下面评论中提到的帖子之后,我找到了一种创建HttpContext会话并应用于IPrincipal该会话的方法。这工作正常,直到单元测试进入控制器,其中HttpContextIPrincipal User对象都再次为空。

由于似乎我正在使用的控制器实例的HttpContext属性为只读(以及该IPrincipal User属性),有没有人知道一种方法来传递HttpContext正在测试的控制器内的单元测试中使用的对象?另外,如果这是不可能的,那么RouteValues使用 ReSharper 的单元测试进行测试的可用方法是什么?

    [SetUp]
    public void SetUp()
    {
        _controlAgtTran = new AgentTransmissionController();

        /****Set up Current HTTP Context to pass Security.cs checks*****/

        //Set up the HTTP Request
        var httpRequest = new HttpRequest("", "http://localhost:2574/", "");

        //Set up the HTTP Response
        var httpResponse = new HttpResponse(new StringWriter());

        //Set up the HTTP Context
        var httpContext = new HttpContext(httpRequest, httpResponse);

        var sessionContainer = new HttpSessionStateContainer("NEAROD",
                                                             new SessionStateItemCollection(),
                                                             new HttpStaticObjectsCollection(),
                                                             100,
                                                             true,
                                                             HttpCookieMode.AutoDetect,
                                                             SessionStateMode.InProc,
                                                             false);

        httpContext.Items["AspSession"] =
            typeof (HttpSessionState)
                .GetConstructor(
                    BindingFlags.NonPublic | BindingFlags.Instance,
                    null,
                    CallingConventions.Standard,
                    new[] {typeof (HttpSessionStateContainer)},
                    null)
                .Invoke(new object[] {sessionContainer});

        //Assign the context
        HttpContext.Current = httpContext;
    }

    [Test]
    public void a01_IncompleteRecordGoesToEdit()
    {

        AgentTransmission agtTran = new AgentTransmission();
        agtTran.ReferenceNumber = 95820518787;
        agtTran.ReferenceType = "S";
        agtTran.EffectiveDate = DateTime.Now;
        agtTran.RelationshipEffDate = DateTime.Now;
        agtTran.RecordStatus = "N";
        agtTran.CreatedDate = DateTime.Now;
        agtTran.CreatedOperator = "xTest1";
        agtTran.FirstName = "Unit";
        agtTran.LastName = "Test";
        agtTran.ExtRepType = "EXTREPID";
        agtTran.JIT = true;
        agtTran.SendToDRM = true;
        agtTran.SendToNMF = true;
        agtTran.WelcomeLetter = true;
        agtTran.OverrideRegionInd = false;

        //set IPrincipal 
        string[] roles = {"LCO"};
        IPrincipal principal = new GenericPrincipal(new GenericIdentity("SYMETRA\\NEAROD"), roles);
        HttpContext.Current.User = principal;
        IPrincipal user = HttpContext.Current.User;

        Assert.AreEqual(user, principal); //This passes
        Assert.AreEqual(principal, _controlAgtTran.User); //this fails

        var result = (RedirectToRouteResult)_controlAgtTran.Create(agtTran); //this crashes

        //Tests aren't run
        Assert.IsNotNull(result);
        Assert.AreEqual(3, result.RouteValues.Count);
        Assert.AreEqual("AgentTransmission", result.RouteValues["controller"]);
        Assert.AreEqual("Edit", result.RouteValues["action"]);
    }
4

1 回答 1

1

Following a similar solution mentioned in this post I added the following to the end of the SetUp() method.

        var controllerCtx = new ControllerContext();
        controllerCtx.HttpContext = new HttpContextWrapper(HttpContext.Current);
        _controlAgtTran.ControllerContext = controllerCtx;

Wrapping the current HttpContext inside an HttpContextBase property (the inappropriately named controllerCtx.HttpContext) the test now has access to the User and HttpContext properties of the controller. These properties were previously read-only when using just the HttpContext.Current session and therefore always null.

FYI - this is my first time unit testing with these objects so that explanation may be less than 100% correct. Please feel free to comment below and I'll make any necessary changes.

于 2014-04-17T20:56:14.603 回答