2012-04-30 7 views
7

Estoy escribiendo algunas pruebas de unidad y me pregunto si es ventajoso burlarse del Cache y, de ser así, ¿cómo?Mocking System.Web.Caching.Cache: ¿simula o comprueba null?

Actualmente en mis pruebas me estoy burlando de la HttpContextBase y envolviéndolo en una costumbre HttpContextFactory:

var mockedHttpContextBase = new Mock<HttpContextBase>(); 

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

y cuando mi código consume una IHttpContextFactory puedo comprobar si la caché es nulo antes de hacer nada con él.

var cache = _httpContextFactory.Current.Cache; 

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

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

Es correcto para comprobar por ser nula como esto cada vez que lo uso o le burlarse de la memoria caché también en la prueba de modo que no es nula cuando se ejecutan las pruebas unitarias de la caché?

Respuesta

3

Si su código se supone caché puede ser null y realiza controles antes de acceder a ella (como lo hace ahora), es necesario tener dos pruebas unitarias para cada acceso caché: existe

  • caché y el tema es almacenada y recuperada (comprobación GetOrStore llamada)
  • caché es nulo y sólo tiene que valer delegado invocación

Si este es el patrón común (comprobación nula), en lugar de tener dos pruebas cada vez que se requiere la dependencia de la memoria caché, sugiero que se ajuste a Null Object Pattern y que se pruebe una vez y luego simplemente use NOP como una dependencia que se puede burlar.

Editar: cache "burlarse" ejemplo

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

Gracias Jimmy. Con respecto al punto 1, ¿cómo escribirías una prueba que depende del caché existente? ¿Cómo se burlaría de la caché en este caso para realizar la prueba? –

+0

@JamieDixon: no se puede burlar 'Cache' ya que está sellado; tendrás que preconfigurarlo usando la implementación real de 'Cache' y hacer que tu' HttpContextBase' simule devolver ese caché preconfigurado cuando se solicite. He agregado un ejemplo a mi publicación. –

+0

Gracias de nuevo Jimmy. Aprecio tu tiempo y ayuda. He agregado una respuesta después de hacer más búsquedas. Parece que usar 'HttpRuntime.Cache' es más apropiado ya que creará una instancia de todo lo que necesita para trabajar, ya que' System.Web.Caching.Cache' arrojará 'NullReferenceExeption' si todo no está configurado. –

13

Después de un poco de búsqueda, parece que puedo utilizar en lugar de HttpRuntime.CacheSystem.Web.Caching.Cache al escribir mis pruebas unitarias.

tal que:

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

El caché nunca debe ser null (sería una excepción adecuada si fuera) así que puede eliminar la referencia nula comprobación de mi código.

+0

Buen movimiento para eludir el System.Web.Caching.Cache sellado no movible con HttpRuntime.Cache – BozoJoe

+0

Esto no funcionó para mí porque mis pruebas son asincrónicas. Por lo tanto, 'HttpRuntime.Cache' comparte estado, y no por prueba. Funciona cuando se ejecutan pruebas de forma individual. –

+0

Para ser claros, en este caso no instancia una memoria caché. Simplemente agregue sus artículos a HttpRuntime.Cache antes de usar la versión simulada. 'HttpRuntime.Cache.Add (cacheKey, sampleUser, null, DateTime.Now.AddHours (2), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null); var context = new Mock (); context.Setup (x => x.Cache) .Returns (HttpRuntime.Cache); ' – Lavamantis