2009-04-23 25 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

編輯:我發現了一個更簡單的方法來做到這一點,至少當你空緩存測試。使用HttpRunTime.Cache作爲您對HttpContext的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類的實例並返回它,因爲它有一個公共構造函數。使用模擬的優點是你可以通過期望來驗證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

我會建議使用微軟的新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的引用。稍後,當您決定單元測試這些相同的方法時,緩存對象仍然可用並且不會爲空。 (因爲它不依賴於HttpContext。)

這樣你甚至不一定需要模擬緩存組件。

+1

偉大的筆記真的幫助這使整個過程更簡單 – P6345uk 2016-04-05 09:29:31