2009-04-23 9 views
17

単体テストのControllerContextオブジェクトにキャッシュオブジェクトをモックする方法はありますか?私は運のない次のようなラッパークラスを作成しようとしました(キャッシュオブジェクトは密封クラスなので)。あなたはどのように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; 

答えて

20

EDIT:私は、これを行うための簡単な方法を発見し、少なくともあなたは、空のキャッシュでテストしているとき。 HttpContextのCacheプロパティに対する期待値の戻り値としてHttpRunTime.Cacheを使用します。より高度なシナリオでは、ラッパーとモックを使用する方が、キャッシュから例外をテストする必要がある場合など、それを処理するより良い方法かもしれません。

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

オリジナル

ラッパークラスを移動するための方法ですが、私はあなたが間違った場所にそれを適用していると思います。コントローラにCacheWrapperプロパティを与え、このプロパティを設定できるCacheWrapperインスタンスを渡すためのコンストラクタを作成します。デフォルトでは、コントローラはHttpContext.Current.Cacheを使用してCacheWrapperを作成します。あなたのテストコードで、コントローラのコンストラクタに渡すための模擬CacheWrapperを構築します。この方法では、モックCacheオブジェクトを作成する必要はありません。密閉されたクラスなので、難しいです。

また、パブリックコンストラクタが存在するため、Cacheクラスのインスタンスをインスタンス化して返すこともできます。モックを使用すると、キャッシュが期待通りに使用されていることを確認できるという利点があります。そのため、おそらくラッパーを使用します。

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

あなたはTypemock Isolatorを使用しようとすることができ、それは箱から出して密封されたクラスを偽装し、あなたはこれらのラッパーを必要としません。

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

私はMicrosoftの新しいMemoryCache.Defaultアプローチを使用することをお勧めします。 .NET Framework 4.0以降を使用し、System.Runtime.Cachingへの参照を含める必要があります。 >http://msdn.microsoft.com/en-us/library/dd997357(v=vs.100).aspx

Webおよび非Webアプリケーションの両方のために働くMemoryCache.Default -

はこちらの記事を参照してください。したがって、あなたのWebアプリケーションを更新して、HttpContext.Current.Cacheへの参照を削除し、それらをMemoryCache.Defaultへの参照で置き換えることです。後で、これらの同じメソッドを単体テストすることを決めると、キャッシュオブジェクトは引き続き使用でき、nullにはなりません。 (HttpContextに依存しないため)

この方法では、キャッシュコンポーネントをモックする必要はありません。

+1

大きな助言が本当に助けになり、全体のプロセスが簡単になりました – P6345uk

関連する問題