2010-08-15 17 views
9

Ho bisogno di falsificare la tabella HttpContext.Current.Application per accedervi dai miei test di unità.Come posso falsificare HttpContext per i test unitari?

Ho bisogno di memorizzare i miei dati da qualche parte. Ho pensato di poter passare l'istanza di NameValueCollectionBase ma, come ho scoperto, questo tipo di base non ha l'indicizzatore, quindi sembra troppo complicato da usare.

Quindi, cosa dire di simulare questa parte di HttpContext? È possibile? Come posso farcela? Sarà NUnit.Mocks utile?

Grazie in anticipo ...

risposta

1

Se avete bisogno di indici per la base NameValueCollection Si prega di utilizzare il codice

public static IEnumerable<KeyValuePair<string, string>> ToPairs(this NameValueCollection collection) 
{ 
    if(collection == null) 
    { 
     throw new ArgumentNullException("collection"); 
    } 

    return collection.Cast<string>().Select(key => new KeyValuePair<string, string>(key, collection[key])); 
} 

Per solo per memorizzare i dati e passando intorno metodi di prova si prega usa sopra il codice.

2
+0

Il problema è che se si tratta di 'Utente', allora è facile restituire nuovo oggetto di tipo' IPrincipal', ma quando si tratta di 'Applicazione', allora ho bisogno di restituire qualche oggetto' HttpApplicationState' che non ha un costruttore pubblico e grazie al suo uso attraverso gli indicizzatori è difficile fingere con 'NUnit.Mocks' ... Puoi fornirmi qualche esempio di codice per questo caso? –

+0

Ciao, Se avete bisogno di indici per la base NameValueCollection Si prega di utilizzare il codice public static IEnumerable > ToPairs (questa collezione NameValueCollection) { se (raccolta == null) { tiro nuove ArgumentNullException ("collection"); } raccolta di ritorno. (). Selezionare (chiave => nuovo KeyValuePair (chiave, raccolta [chiave])); } Per memorizzare solo i dati e passare i metodi di test, utilizzare il codice sopra riportato. Il primo collegamento – Venkat

+2

non funziona –

0

In questo scenario vengono generati alcuni stub derivati ​​dalle classi di base in System.Web.Abstractions. Io uso spesso questa tecnica per le applicazioni MVC come controller/WebAPI MVC contengono un'astrazione per HttpContext (HttpContextBase)

In questo modo posso spegnere HttpContext requisiti nel mio test di unità/integrazione, ecco un campione ...

public class MockHttpApplicationState : HttpApplicationStateBase 
{ 
    private IDictionary<string, object> _appState = new Dictionary<string, object>(); 

    public override void Add(string name, object value) 
    { 
     _appState.Add(name, value); 
    } 

    public override object Get(string name) 
    { 
     return _appState[name]; 
    } 

    public override object this[string name] 
    { 
     get 
     { 
      return _appState[name]; 
     } 

     set 
     { 
      _appState[name] = value; 
     } 
    } 
} 

public class MockHttpContext : HttpContextBase 
{ 
    private IDictionary<string, object> _appKeys; 

    public MockHttpContext() 
    { 

    } 

    /// <summary> 
    /// Accepts a dictionary of app keys to supply to the HttpApplicationState instance 
    /// </summary> 
    /// <param name="applicationState"></param> 
    public MockHttpContext(IDictionary<string,object> applicationState) 
    { 
     _appKeys = applicationState; 
    } 

    public override Cache Cache 
    { 
     get 
     {     
      return HttpRuntime.Cache; 
     } 
    } 

    public override HttpApplicationStateBase Application 
    { 
     get 
     { 
      var mockAppState = new MockHttpApplicationState(); 

      foreach (string key in _appKeys.Keys) 
      { 
       mockAppState.Add(key, _appKeys[key]); 
      } 

      return mockAppState; 
     } 
    } 

    public override HttpRequestBase Request 
    { 
     get 
     { 
      return new HttpRequestWrapper(new HttpRequest(null,"http://localhost",null)); 
     } 
    } 
} 

Poi il mio test può stabilire controller e Http Contesto:

private readonly OnlineShop.MVC.Controllers.HomeController _controller = 
     new MVC.Controllers.HomeController(null,new UnitOfWork()); 

    [OneTimeSetUp] 
    public void Init() 
    { 
     var appKeys = new Dictionary<string, object>(); 

     appKeys.Add("localhost", 1); 

     var httpContext = new MockHttpContext(appKeys); 

     _controller.ControllerContext = new ControllerContext() 
     { 
      Controller = _controller, 
      RequestContext = new RequestContext(httpContext, new RouteData())  
     };       
    } 

    [Test] 
    public void Index_Returns_HomeView() 
    {    
     var view = _controller.Index() as ViewResult; 
     var viewModel = view.Model as MVC.ViewModels.Home; 

     Assert.IsInstanceOf<OnlineShop.MVC.ViewModels.Home>(viewModel); 
     Assert.IsTrue(viewModel.FeaturedProducts.Count > 0); 
    } 

e il mio controller è a conoscenza del suo ambiente HttpContextBase esempio fornendo la cache ei Applicazione stato:

public ActionResult Index() 
    {       
     string cacheKey = string.Format("FeaturedProducts-{0}",WebsiteId); 
     IList<Product> productList = this.HttpContext.Cache[cacheKey] as IList<Product>; 


     //My app keeps a list of website contexts in the Application. This test returns 1 based on the unit/int tests or a real world db value when hosted on IIS etc.. 
     int websiteId = (int)HttpContext.Application[this.Request.Url.Host]; 
Problemi correlati