2013-04-18 2 views
1

단위 테스트를 실행할 때 다음 오류가 발생합니다. NullReferenceException이 사용자 코드에 의해 처리되지 않았습니다. 개체 참조가 개체의 인스턴스로 설정되지 않았습니다.UnitTest MVC에서 httpcontext를 처리하는 방법

어디서 잘못 될지 잘 모르겠습니다. 제발 조언.

내 SessionManager.cs 클래스

public static int customerID 
{ 
    get 
    { 
     if (HttpContext.Current.Session != null && 
      HttpContext.Current.Session[_customerID] != null) 
     { 
      return Convert.ToInt32(HttpContext.Current.Session[_customerID]); 
     } 
     else 
     { 
      throw new Ramsell.ExceptionManagement.RamsellException(); 
     } 
    } 
    set 
    { 
     if (HttpContext.Current.Session == null) return; 
     HttpContext.Current.Session[_customerID] = value; 

    } 
} 

ParticipantController

public ActionResult Index() 
{ 
    int custId = Convert.ToInt32(SessionManager.customerID); 
    //code logic about participant lists 
    return View(); 
} 

시험 방법 :

[TestMethod] 
    public void IndexTest() 
    { 
     ParticipantController pCTarget = new ParticipantController(); 
     const int page = 1; 
     const string sortBy = "FirstName"; 
     const bool ascending = true; 
     const string partname = ""; 
     const int success = -1; 
     const string id = ""; 
     var expected = typeof(ParticipantListViewModel); 
     ViewResult result = pCTarget.Index(page, sortBy, ascending, partname, success, id) as ViewResult; 
     Assert.AreEqual(expected, result.Model.GetType()); 

    } 

//이 내 모의 클래스입니다

public Mock<RequestContext> RoutingRequestContext { get; private set; } 
public Mock<HttpContextBase> Http { get; private set; } 
    public Mock<HttpServerUtilityBase> Server { get; private set; } 
    public Mock<HttpResponseBase> Response { get; private set; } 
    public Mock<HttpRequestBase> Request { get; private set; } 
    public Mock<HttpSessionStateBase> Session { get; private set; } 
    public Mock<ActionExecutingContext> ActionExecuting { get; private set; } 
    public HttpCookieCollection Cookies { get; private set; } 

    public MockContext() 
    { 
     this.RoutingRequestContext = new Mock<RequestContext>(MockBehavior.Loose); 
     this.ActionExecuting = new Mock<ActionExecutingContext>(MockBehavior.Loose); 
     this.Http = new Mock<HttpContextBase>(MockBehavior.Loose); 
     this.Server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose); 
     this.Response = new Mock<HttpResponseBase>(MockBehavior.Loose); 
     this.Request = new Mock<HttpRequestBase>(MockBehavior.Loose); 
     this.Session = new Mock<HttpSessionStateBase>(MockBehavior.Loose); 
     this.Cookies = new HttpCookieCollection(); 

     this.RoutingRequestContext.SetupGet(c => c.HttpContext).Returns(this.Http.Object); 
     this.ActionExecuting.SetupGet(c => c.HttpContext).Returns(this.Http.Object); 
     this.Http.SetupGet(c => c.Request).Returns(this.Request.Object); 
     this.Http.SetupGet(c => c.Response).Returns(this.Response.Object); 
     this.Http.SetupGet(c => c.Server).Returns(this.Server.Object); 
     this.Http.SetupGet(c => c.Session).Returns(this.Session.Object); 
     this.Request.Setup(c => c.Cookies).Returns(Cookies); 

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

     this.Session.Setup(c => c.Add("AspSession", typeof(HttpSessionState).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance, 
            null, CallingConventions.Standard, 
            new[] { typeof(HttpSessionStateContainer) }, 
            null) 
          .Invoke(new object[] { sessionContainer }))); 
    } 
,

답변

2

컨트롤러에 대한 단위 테스트를 작성할 때는 컨트롤러의 종속성을 조롱해야합니다. (샘플

public interface ISessionManager 
{ 
    int CustomerID { get; set; } 
} 

public class HttpSessionManager : ISessionManager 
{ 
    // your current implementation goes here 
} 

다음이 추상화를 조롱하고 컨트롤러에 주입 : 그래서, (클래스가 아닌 정적하고 관리자 클래스 ISessionManager 인터페이스를 추출) 컨트롤러 추상화보다는 구체적인 SessionManager 구현에 달려 있는지 확인) MOQ로 :

public class ParticipantController : Controller 
{ 
    private readonly ISessionManager _sessionManager; 

    public ParticipantController(ISessionManager sessionManager) 
    { 
     _sessionManager = sessionManager; 
    } 

    public ActionResult Index() 
    { 
     int custId = _sessionManager.CustomerID; 
     //code logic about participant lists 
     return View(); 
    } 
} 

주 단위 t의 목표 : 여기

[TestMethod] 
public void IndexTest() 
{ 
    var sessionManager = new Mock<ISessionManager>(); // Mock dependency 
    sessionManager.Setup(m => m.CustomerID).Returns(42); 

    const int page = 1; 
    const string sortBy = "FirstName"; 
    const bool ascending = true; 
    const string partname = ""; 
    const int success = -1; 
    const string id = ""; 
    var expectedModelType = typeof(ParticipantListViewModel); 
    ParticipantController pCTarget = 
     new ParticipantController(sessionManager.Object); // Inject dependency 

    var view = pCTarget.Index(page, sortBy, ascending, partname, success, id) 
       as ViewResult; 

    sessionManager.VerifyGet(m => m.CustomerID); // Verify dependency was called 
    Assert.AreEqual(expectedModelType, view.Model.GetType()); 
} 

그리고 컨트롤러 코드 esting은 코드의 모든 작은 부분이 예상대로 작동하는지 확인하는 것입니다. 테스트중인 다른 유닛에 의존한다면 테스트는 두 가지 이유로 실패 할 수 있습니다. 테스트중인 유닛이 예상대로 작동하지 않거나 종속성에 이상이 있습니다. 이미 세션 관리자가 예외를 throw하여 컨트롤러 테스트에 실패했습니다. 테스트 결과 컨트롤러가 예상대로 작동하지 않는다고합니다. 사실입니까? 아니오 - 세션 관리자가 예상대로 작동하지 않습니다.

+1

Perfect Thanks @ lazyberezovsky – Kdev

관련 문제