【问题标题】:NullReference durning testing controller with NUnit and Moq使用 NUnit 和 Moq 测试控制器期间的空引用
【发布时间】:2016-09-12 14:22:36
【问题描述】:

我在测试中获得了 NullReference 异常。当我在控制器中评论 eventsRepository.AddEvent(eve, User.Identity.GetUserId()); 时,它会通过。

我该如何解决?

控制器的方法

[ValidateAntiForgeryToken]
[HttpPost]
[Authorize]
public ActionResult CreateEvent(Event eve)
{
    if (eve.DateOfBegining < DateTime.Now)
    {
        ModelState.AddModelError("DateOfBegining", "");
    }

    if (eve.MaxQuantityOfPlayers < eve.MinCount)
    {
        ModelState.AddModelError("MinCount", "");
    }

    if (eve.ConflictSides.Count < 2 || eve.ConflictSides.Count > 10)
    {
        ModelState.AddModelError("ConflictSides", "");
    }

    if (!ModelState.IsValid)
    {
        return View("CreateEvent", eve);
    }
    else
    {
        eventsRepository.AddEvent(eve, User.Identity.GetUserId());
        return RedirectToAction("EventsList");
    }
}

添加事件

void AddEvent(Event ev, string userId);

测试方法

[TestMethod]
public void CreateEvent_AddEvent_returns_EventsList()
{
    // arrange
    var EventRepo = new Mock<IEventRepository>();
    var ParticipantsRepo = new Mock<IParticipants>();

    DateTime dt = new DateTime(2200, 1, 23);
    Event eve = new Event() 
    {
        ConflictSides = new List<ConflictSide>() { 
                                                new ConflictSide{ Name ="niebiescy"},
                                                new ConflictSide{ Name ="czerwoni"},
                                                new ConflictSide{ Name ="fioletowi"},
                                                },
        DateOfBegining = dt,
        Description = "bardzo dlugi opid na potrzeby testu",
        EventCreator= "userId",
        EventName = "najlepsza",
        FpsLimitInBuildings=300,
        FpsLimitOnOpenField=500,
        Hicap = new MagazineTyp(){ifAllow = true, ifOnlySemi = false},
        MidCap = new MagazineTyp(){ifAllow = true, ifOnlySemi = false},
        LowCap = new MagazineTyp(){ifAllow = true, ifOnlySemi = false},
        RealCap = new MagazineTyp(){ifAllow = true, ifOnlySemi = false},
        MaxQuantityOfPlayers = 50,
        MinCount = 10           
    };

    var target = new EventController(EventRepo.Object, ParticipantsRepo.Object);

    // act

    RedirectToRouteResult result = target.CreateEvent(eve) as RedirectToRouteResult;

    // assert

    // EventRepo.Verify(a => a.AddEvent(It.IsAny<Event>(), It.IsAny<string>()), Times.Once());

    Assert.AreEqual("EventsList", result.RouteValues["action"]);
}

【问题讨论】:

  • 您正在访问User.Identity.GetUserId(),但您的测试方法中没有设置控制器的用户属性。
  • 这是用 fakeiteasy stackoverflow.com/a/39898952/2672291 模拟它的另一种方法

标签: c# asp.net-mvc unit-testing nunit moq


【解决方案1】:

您正在访问User.Identity.GetUserId(),但控制器的User 属性未在您的测试方法中设置,因此访问时它将为空

您需要使用虚拟用户帐户设置控制器上下文。这是一个帮助类,您可以使用它来模拟获取用户主体所需的HttpContext

private class MockHttpContext : HttpContextBase {
    private readonly IPrincipal user;

    public MockHttpContext(string username, string[] roles = null) {
        var identity = new GenericIdentity(username);
        var principal = new GenericPrincipal(identity, roles ?? new string[] { });
        user = principal;
    }

    public override IPrincipal User {
        get {
            return user;
        }
        set {
            base.User = value;
        }
    }
}

在初始化目标控制器后的测试中,您需要设置控制器上下文

//...other coder

var target = new EventController(EventRepo.Object, ParticipantsRepo.Object);
target.ControllerContext = new ControllerContext {
    Controller = target,
    HttpContext = new MockHttpContext("fakeuser@example.com")
};

//...other coder

【讨论】:

    猜你喜欢
    • 2016-06-15
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多