2016-09-12 47 views
1

我在測試中獲得了NullReference異常。當我評論eventsRepository.AddEvent(eve,User.Identity.GetUserId());在控制器比它通過。使用NUnit和Moq測試控制器的NullReference

我該如何解決?

控制器的方法

[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"); 
    } 
} 

的addEvent

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"]); 
} 
+0

您正在訪問'User.Identity.GetUserId()'但控制器的用戶屬性沒有在您的測試方法中設置。 – Nkosi

+0

繼承人另一種方式來嘲笑它與fakeiteasy http://stackoverflow.com/a/39898952/2672291 – Haohmaru

回答

1

你是訪問ing 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("[email protected]") 
}; 

//...other coder 
+0

非常感謝。這很有幫助:) – pred

相關問題