2012-04-30 16 views
7

Sto scrivendo qualche test unitario e mi chiedo se sia vantaggioso deridere lo Cache e se sì, come?Mocking System.Web.Caching.Cache - Mock o controlla null?

Attualmente nel mio test ho beffarda la HttpContextBase e avvolgendolo in un costume HttpContextFactory:

var mockedHttpContextBase = new Mock<HttpContextBase>(); 

IHttpContextFactory httpContextFactory = new HttpContextFactory 
{ 
    Current = mockedHttpContextBase.Object 
}; 

e quando il mio codice consuma in IHttpContextFactory ho verificare se la cache è nullo prima di fare qualsiasi cosa con esso.

var cache = _httpContextFactory.Current.Cache; 

Func<SomeReturnType> doSomeWork =() => _foo.someMethodIExecute(param1,param2); 

return cache != null ? cache.GetOrStore("doSomeWorkCacheKey",doSomeWork, 900) 
        : doSomeWork.Invoke(); 

è giusto per verificare la cache essere nulla come questo ogni volta che lo uso o si deridere la cache anche nel test in modo che non è nulla quando si esegue il test di unità?

risposta

3

Se il codice si presuppone cache può essere null ed esegue i controlli prima di accedervi (come accade oggi), è necessario disporre di due test di unità per ogni accesso della cache:

  • di cache esiste e reca conservati e recuperati (controllo GetOrStore chiamata)
  • cache è nullo e semplicemente affermare delegato invocazione

Se questo è modello comune (controllo null), invece di avere due test ogni volta che è richiesta la dipendenza dalla cache, suggerisco di inserirla in Null Object Pattern e farla provare una volta e più tardi semplicemente usando NOP come dipendenza che può essere derisa.

Edit: cache "beffardo" esempio

var cache = new Cache(); 
// Add takes more parameters; fill whatever is necessary to make it work 
cache.Add("doSomeWorkCacheKey", doSomeWork, ...); 
var mockedHttpContextBase = new Mock<HttpContextBase>(); 
// tell your mock to return pre-configured cache 
mockedHttpContextBase.Setup(m => m.Cache).Returns(cache); 

IHttpContextFactory httpContextFactory = new HttpContextFactory 
{ 
    Current = mockedHttpContextBase.Object 
}; 
+0

Grazie Jimmy. Per quanto riguarda il punto 1, come scriveresti un test che dipende dalla cache esistente? Come deriderei la cache in questo caso per eseguire il test? –

+0

@JamieDixon: non si può realmente prendere in giro 'Cache' dato che è sigillato; dovrai preconfigurarlo usando un'implementazione reale di 'Cache' e rendere il tuo simulatore' HttpContextBase' restituire quella cache preconfigurata quando richiesto. Ho aggiunto un esempio al mio post. –

+0

Grazie ancora Jimmy. Apprezzo il tuo tempo e il tuo aiuto. Ho aggiunto una risposta io stesso dopo aver fatto più ricerche. Sembra che l'uso di 'HttpRuntime.Cache' sia più appropriato dato che istanzia tutto ciò di cui ha bisogno per funzionare dove' System.Web.Caching.Cache' genererà 'NullReferenceExeption' se tutto non è configurato. –

13

Dopo un po 'di ricerche, sembra che posso usare HttpRuntime.Cache invece di System.Web.Caching.Cache durante la scrittura di mio test di unità.

Tale che:

var mockedHttpContextBase = new Mock<HttpContextBase>(); mockedHttpContextBase.Setup(m => m.Cache).Returns(HttpRuntime.Cache);

La cache non dovrebbe mai essere null (sarebbe un'eccezione appropriata se fosse) così posso eliminare il riferimento null controllare dal mio codice.

+0

Buona mossa aggirando l'unMoq'able sigillato System.Web.Caching.Cache con HttpRuntime.Cache – BozoJoe

+0

Questo non ha funzionato per me perché i miei test sono asincroni. Pertanto, 'HttpRuntime.Cache' condivide lo stato e non per test. Funziona quando si eseguono i test individualmente. –

+0

Per essere chiari, in questo caso non istanziate una cache. Basta aggiungere i tuoi articoli a HttpRuntime.Cache prima di utilizzare la versione derisoria. 'HttpRuntime.Cache.Add (cacheKey, sampleUser, null, DateTime.Now.AddHours (2), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); contesto var = new Mock (); context.Setup (x => x.Cache) .Returns (HttpRuntime.Cache); ' – Lavamantis