2010-01-03 97 views
2

我希望能夠模擬webforms Page對象上的ClientScriptManager類, 但是看起來我不能,我得到了我無法模擬密封的錯誤類。使用Rhino Mocks創建ClientScriptManager的模擬

MockRepository mocks = new MockRepository() 

Page page = mocks.PartialMock<Page>(); 

var clientScript = mocks.PartialMock<ClientScriptManager>(); //error here 

SetupResult.For(page.ClientScript).Return(clientScript); 

有關如何嘲笑clientscriptmanager的任何意見,將不勝感激。

回答

4

正如您發現的那樣,您不能使用大多數模擬庫來模擬密封類型。其中一個原因是,許多模擬庫通過創建派生類型來運行,但是如果該類是密封的,那麼它們不能從中派生出來。

我們在微軟內部完成的工作是我們使用手寫的IClientScriptManager接口,然後使用ClientScriptManagerWrapper實現該接口並將所有調用委託給實際的ClientScriptManager

然後無論什麼類型需要使用ClientScriptManager它將代替IClientScriptManager。在運行時,我們創建一個ClientScriptManagerWrapper(並傳入實際的ClientScriptManager)。在測試時間,我們使用一個模擬對象庫來創建一個模擬IClientScriptManager並使用它。

下面是一個代碼示例:

public class SomeClassThatNeedsClientScriptManager { 
    private IClientScriptManager _iClientScriptManager; 

    public IClientScriptManager IClientScriptManager { 
     get { 
      if (_iClientScriptManager == null) { 
       _iClientScriptManager = new ClientScriptManagerWrapper(Page.ClientScriptManager); 
      } 
      return _iClientScriptManager; 
     } 
     set { 
      _iClientScriptManager = value; 
     } 
    } 

    public void SomeMethodThatUsesClientScriptManager() { 
     IClientScriptManager.RegisterClientScriptBlock(typeof(Whatever), "key", "alert('hello')"); 
    } 
} 

public interface IClientScriptManager { 
    void RegisterClientScriptBlock(Type type, string key, string script); 
} 

public class ClientScriptManagerWrapper : IClientScriptManager { 
    private readonly ClientScriptManager _clientScriptManager; 

    public ClientScriptManagerWrapper(ClientScriptManager clientScriptManager) { 
     if (clientScriptManager == null) { 
      throw new ArgumentNullException("clientScriptManager"); 
     } 
     _clientScriptManager = clientScriptManager; 
    } 

    public void RegisterClientScriptBlock(Type type, string key, string script) { 
     _clientScriptManager.RegisterClientScriptBlock(type, key, script); 
    } 
} 

然後,您可以修改IClientScriptManager接口和ClientScriptManagerWrapper有你需要的任何方法。

+0

這太糟糕了,這是內部的。我希望看到更多的Framework類型實現公共接口和包裝,以便可測試的代碼可以與更少的層進行互操作。但這就是爲什麼我們傾向於包裝包裝。 :) – maxwellb 2014-01-17 23:01:02

+0

@maxwellb的確,如果你看看大多數較新的框架(當然在ASP.NET空間中),你會看到更多的接口和抽象基類。例如,MVC,Web API和SignalR都大量使用接口,這使得這種場景更容易實現。 – Eilon 2014-01-20 17:06:16