2009-04-23 8 views
17

Comment est-ce que je me moquerais de l'objet de mise en cache sur l'objet ControllerContext pour mes tests unitaires? J'ai essayé de créer une classe wrapper comme suit (puisque l'objet cache est une classe scellée) sans chance.Comment vous moquez-vous de l'objet de mise en cache dans asp.net mvc?

var mockControllerContext = new Mock<ControllerContext>(); 
var mockhttpContext = new Mock<HttpContextBase>();    

mockhttpContext.SetupGet(o => o.Cache).Returns(
     new CacheWrapper(mockControllerContext.Object.HttpContext.Cache)); 

mockControllerContext.SetupGet(
          o => o.HttpContext).Returns(mockhttpContext.Object); 
this.tennisMatchupController.ControllerContext = mockControllerContext.Object; 

Répondre

20

EDIT: J'ai trouvé un moyen plus facile de le faire, au moins lorsque vous testez avec un cache vide. Utilisez HttpRunTime.Cache comme valeur de retour pour votre attente sur la propriété Cache du HttpContext. Pour les scénarios plus avancés, l'utilisation d'un wrapper et de moqueurs peut toujours être un meilleur moyen de le gérer - par exemple, si vous avez besoin de tester des exceptions à partir du cache.

var httpContext = MockRepository.GenerateMock<HttpContextBase>(); 
httpContext.Expect(h => h.Cache).Return(HttpRunTime.Cache).Repeat.Any() 

originale:

La classe wrapper est le chemin à parcourir, mais je pense que vous l'appliquez au mauvais endroit. Je donnerais à mon contrôleur une propriété CacheWrapper, puis créerais un constructeur qui me permettrait de passer une instance CacheWrapper à laquelle cette propriété peut être définie. Par défaut, le contrôleur crée un CacheWrapper en utilisant HttpContext.Current.Cache. Dans votre code de test, construisez un CacheWrapper pour passer dans le constructeur du contrôleur. De cette façon, vous n'avez pas du tout besoin de créer un faux objet Cache, ce qui est difficile car c'est une classe scellée. Alternativement, vous pouvez simplement instancier une instance de la classe Cache et la renvoyer, car il existe un constructeur public pour celle-ci. L'utilisation de la maquette a l'avantage que vous pouvez vérifier que le cache est utilisé en fonction des attentes, cependant, j'irais probablement avec le wrapper.

public class CacheWrapper 
{ 
    private Cache Cache { get; set; } 

    public CacheWrapper() 
    { 
    this.Cache = HttpContext.Current.Cache; 
    } 

    public virtual Object Add(string key, 
          Object value, 
          CacheDependency dependencies, 
          DateTime absoluteExpiration, 
          TimeSpan slidingExpiration, 
          CacheItemPriority priority, 
          CacheItemRemovedCallback onRemoveCallback) 
    { 
    this.Cache.Add(key, 
        value, 
        dependencies, 
        absoluteExpiration, 
        slidingExpiration, 
        priority, 
        onRemoveCallback); 
    } 

    ...wrap other methods... 
} 


public class BaseController : Controller 
{ 
    private CacheWrapper { get; set; } 

    public BaseController() : this(null) { } 

    public BaseController(CacheWrapper cache) 
    { 
     this.CacheWrapper = cache ?? new CacheWrapper(); 
    } 
} 

[TestMethod] 
public void CacheTest() 
{ 
    var wrapper = MockRepository.GenerateMock<CacheWrapper>(); 

    wrapper.Expect(o => o.Add(...)).Return(...); 

    var controller = new BaseController(wrapper); 

    var result = controller.MyAction() as ViewResult; 

    Assert.AreEqual(...); 

    wrapper.VerifyAllExpectations(); 
} 
0

Vous pouvez essayer d'utiliser Typemock Isolator, il Fakes cours scellé de la boîte, de sorte que vous ne aurez pas besoin de ces emballages.

5
HttpContext.Current = new HttpContext(new HttpRequest(null, "http://tempuri.org", null), new HttpResponse(null)); 
11

Je recommanderais d'utiliser une nouvelle approche MemoryCache.Default de Microsoft. Vous devrez utiliser .NET Framework 4.0 ou version ultérieure et inclure une référence à System.Runtime.Caching.

Voir article ici ->http://msdn.microsoft.com/en-us/library/dd997357(v=vs.100).aspx

MemoryCache.Default fonctionne aussi bien pour les applications Web et non-Web. Donc, l'idée est de mettre à jour votre webapp pour supprimer les références à HttpContext.Current.Cache et de les remplacer par des références à MemoryCache.Default. Plus tard, lorsque vous décidez de tester ces mêmes méthodes, l'objet cache est toujours disponible et ne sera pas nul. (Parce qu'il ne dépend pas d'un HttpContext.)

De cette façon, vous n'avez même pas besoin de se moquer du composant de cache.

+1

Une grande note m'a vraiment aidé à simplifier tout le processus – P6345uk

Questions connexes