2016-05-25 25 views
0

Ich versuche, einen Komponententest zu schreiben, um meinen Controller zu testen, der Sitzung verwendet. Ich verstehe das Konzept, dass der httpcontext nur von Anfrage erzeugt wird, die vom Browser ist und seit dem Aufruf einer Controller-Aktion Formular Unit Test, der aktuelle Kontext wird null sein.Unit Testing-Sitzungen gibt immer noch Null nach Mocking

Ich habe versucht, dieses Problem basierend auf dem ersten Teil dieses Artikels http://www.dontpaniclabs.com/blog/post/2011/03/22/testing-session-in-mvc-in-four-lines-of-code/ zu lösen, aber es funktioniert immer noch nicht für mich. Siehe meinen Code unten.

[TestFixtureSetUp] 
    public void Configure_AutoMapper() 
    { 
     _product = new ProductViewModel() 
     { 
      Id = Guid.NewGuid(), 
      Category = Guid.Parse("72E42A11-DFA4-4AB9-A735-5CD5C18396D4"), 
      Brand = Guid.Parse("96E68B67-60FB-4531-898E-815433B44D89"), 
      Description = "From test", 
      CostPrice = Parse("17.00"), 
      SalePrice = Parse("25.00"), 
      Quantity = 7, 
      BusinessId = Guid.Parse("BDF9FB7F-DB40-4365-9872-AECD616ED415") 
     }; 

     var context = new Mock<ControllerContext>(); 
     var session = new Mock<HttpSessionStateBase>(); 
     context.Setup(m => m.HttpContext.Session).Returns(session.Object); 
     _productsController = new ProductsController {ControllerContext = context.Object}; 

     var userSessionInfo = new UserSessionViewModel() 
     { 
      FirstName = "Junior", 
      LastName = "Labolz", 
      BusinessId = Guid.Parse("BDF9FB7F-DB40-4365-9872-AECD616ED415") 
     }; 

     SessionHelper.AddUserDetailsToSession(SessionHelper.UserDetails, userSessionInfo); 
    } 


    [Test] 
    public void Display_Products_List_On_View_Products_Button_Click() 
    { 
     //Set Up 

     //Act 
     var viewResult = (ViewResult)_productsController.Index(); 

     //Assert 
     Assert.That(string.Empty, Is.EqualTo(viewResult.ViewName)); 
    } 


    public static void AddUserDetailsToSession(string sessionName, UserSessionViewModel userSessionDetails) 
    { 
     HttpContext.Current.Session.Add(sessionName, userSessionDetails); 
    } 

** Basierend auf Richard Antwort habe ich es zu **

 var context = new Mock<ControllerContext>(); 
     var session = new Mock<HttpSessionStateBase>(); 
     context.Setup(m => m.HttpContext.Session).Returns(session.Object); 
     var userSessionInfo = new UserSessionViewModel() 
     { 
      FirstName = "Junior", 
      LastName = "Labolz", 
      BusinessId = Guid.Parse("BDF9FB7F-DB40-4365-9872-AECD616ED415") 
     }; 
     context.Object.HttpContext.AddUserDetailsToSession(SessionHelper.UserDetails, userSessionInfo); 

     _productsController = new ProductsController {ControllerContext = context.Object}; 

Produkt Controller Konstruktor

public ProductsController() 
    { 
     _productService = new ProductServiceClient(); 
     _userSessionViewModel = (UserSessionViewModel)SessionHelper.GetSessionDetail(SessionHelper.UserDetails); 
    } 

Session Methode

public static object GetSessionDetail(string sessionName) 
    { 
     return HttpContext.Current.Session[sessionName]; 
    } 
Get

Antwort

0

Ich kann sehen, dass Ihr Code eine statische Funktion enthält, die direkt auf HttpContext.Current verweist. Sie können dies nicht tun, wenn Sie Unit-Tests durchführen möchten. Stattdessen müssen Sie mit den injected-Instanzen von HttpContextBase arbeiten.

In Ihren Komponententests sind diese Instanzen Ihr Mockkontext. In der Produktion würden Sie Ihren Container einrichten, um HttpContext.Current zu injizieren, wenn HttpContextBase angefordert wird.

Ich würde Ihre statische Methode umschreiben eine Erweiterungsmethode sein:

public static void AddUserDetailsToSession(this HttpContextBase context, 
    string sessionName, UserSessionViewModel userSessionDetails) 
{ 
    context.Session.Add(sessionName, userSessionDetails); 
} 

es dann von Ihrem Test nennen:

context.Object.AddUserDetailsToSession(SessionHelper.UserDetails, userSessionInfo); 
+0

Ich bin immer noch ein NULL-Verweis Ausnahme bekommen, vielleicht, weil ich bin auch versuche ich die Session in meinem productController-Konstruktor zu lesen? –

+0

Ich habe meinen Code aktualisiert, bitte sehen Sie nach mir. Ich habe es geändert, um eine Erweiterungsmethode zu verwenden, ich habe einen Titel in meinem Update "basierend auf Richards Antwort". Ich zeige Ihnen auch, was ich in meinem Produktsteuerpult –

+0

habe Sie können HttpContext.Current nirgends verwenden - Sie können HttpContext von dem ControllerContext abrufen. Sie sollten sowieso nicht über den Controllerkonstruktor auf Session zugreifen, da Sie den Kontext zum Zeitpunkt des Aufrufs nicht haben. – Richard