2010-10-18 116 views
4

我有一個類,它執行一些內容檢索,並且它有一個方法需要一些輸入(過濾器)才能檢索它。其中一個「輸入」調用另一個方法,基本上返回一個int,我如何使用MOQ來嘲笑它?這裏有一個例子:如何嘲笑返回一個int與MOQ的方法

namespace MyNamespace 
{ 
    public class ConfigMetaDataColumns : MyModel 
    { 
     public int FieldID { get { return ValueInt("FieldID"); } } 
     public int OrderId { get { return ValueInt("OrderId"); } } 
     public string Label { get { return ValueString("Label"); } } 
     public string FieldName { get { return ValueString("FieldName"); } } 
     public int IsReadOnly { get { return ValueInt("IsReadOnly"); } } 
    } 

    public class GetDataClass 
    { 
     protected OpenSQLAccessLayer m_WITObject; 

     // Input Properties 
     public string GroupID; 
     public string PageName; 

     // Output Properties 

     /// <summary> 
     /// Get Config meta data 
     /// </summary> 
     /// <returns></returns> 
     public IEnumerable<ConfigMetaDataColumns> GetConfigMetaData() 
     { 
      var requester = new ListRequester<OpenSQL, ConfigMetaDataColumns>(m_WITObject, "Result[0].RowCount", "Result[0].Row[{0}]."); 

      return requester.Items; 
     } 

     public void InitRequest() 
     { 
      User user = (User)HttpContext.Current.User; 
      m_WITObject = user.NewService<OpenSQLAccessLayer>(); 

      m_WITObject.SetInput("MultipleResultSets", 1); 
      m_WITObject.SetInput("ClientID", Utils.GetClientID()); 
      m_WITObject.SetInput("GroupID", GroupID); 
      m_WITObject.SetInput("PageName", PageName); 
      m_WITObject.Retrieve(); 
     } 
    } 
} 

這是「GetClientID()」方法:

public static int GetClientID() 
     { 
      User oUser = (User)HttpContext.Current.User; 
      int nClientID; 
      string sClientID = string.Empty; 

      if (String.IsNullOrEmpty(oUser.Session("clientid"))) 
      { 
       Client oClient = new Client(); 
      } 

      oUser = (User)HttpContext.Current.User; 
      sClientID = oUser.Session("clientid"); 




      //If we couldn't retrieve it, throw exception 
      if (string.IsNullOrEmpty(sClientID) || !int.TryParse(sClientID, out nClientID)) 
      { 
       throw new Exception("No clientid found in user session, client not authenticated, please login from main page"); 
      } 

      return nClientID; 
     } 

我只是在尋找一種方式,讓我在一個硬編碼值傳遞的客戶端ID,並使用它對GetDataClass類進行一些單元測試。

謝謝。

+1

沒有回答你的問題,因爲克勞斯比斯科夫已經做了很好的工作。但我想說,而不是一個「Util」類,我喜歡使用一個AppContext類(它實現IAppContext,這與klausbyskov的答案中的IUtil相同)。這存儲了有關應用程序當前上下文的信息,例如當前用戶,當前客戶端或您在整個應用程序中可能需要知道的其他活動配置。這當然是個人偏好,但我認爲AppContext類的意圖比另一個名爲「Utils」的類更清晰。 – NerdFury 2010-10-18 19:56:24

+0

感謝您的建議,不幸的是,這些課程來自不同的團隊,也是我無法改變的「核心」庫的一部分!我只是從它繼承而來。 – Saxman 2010-10-18 21:40:30

回答

5

你不能嘲笑一種靜態方法。你應該使用一些依賴注入的手段。假設你將界面你GetClientId方法部分稱爲IUtils像這樣:

public interface IUtils 
{ 
    int GetClientId(); 
} 

,你有你的具體類如上實施Utils,但沒有方法是靜態的(和實施過程中的界面)。 現在注入你的接口的實現到GetDataClass 類通過改變它的構造,就像這樣:

public class GetDataClass 
{ 
    private readonly IUtils utils; 

    public GetDataClass(IUtils utils) 
    { 
     this.utils = utils; 
    } 

    //SNIP 
} 

InitRequest方法更改呼叫Utils.GetClientID()this.utils.GetClientId()

您現在可以使用模擬來實例GetDataClass類,如下所示:

var utilsMock = new Mock<IUtils>(); 
utilsMock.Setup(u => u.GetClientId()).Returns(42); 

var getDataClass = new GetDataClass(utilsMock.Object); 
getDataClass.InitRequest(); 

就是這樣。

+0

嗨klausbyskov,不幸的是,「Utils」類(以及其他類的負載已經由不同的團隊實現!),沒有一個是實現接口,所以我不能對其進行任何更改。也許,我應該改寫我的問題:基於我原來的問題中的信息,我該如何測試**「GetDataClass」**(它需要調用「** InitRequest」**進行一些初始化),具體來說,調用**「GetConfigMetaData()」**?謝謝。 – Saxman 2010-10-18 21:38:26

+0

是什麼阻止你重構*其他團隊*的代碼?畢竟,你們都在同一條船上。如果你解釋你的代碼可測試的意圖,我相信他們將*必須*盡力滿足你的願望,如果他們不想看起來像專業的傻瓜。從長遠來看,它將會幫助你在開發過程中使用行業最佳實踐,而且絕對包括編寫可測試的代碼。因此,不是尋找一個解決方案(不存在)來解決設計問題,而只是重構代碼。這不應該是一個很大的交易。 – 2010-10-18 21:58:44

+0

這個類(在許多其他類中)是由一個由大約15個不同項目使用的不同團隊編寫的「Core」庫的一部分。我在這裏很新,所以我的聲音就像流水線一樣流暢:)但是很公平,我會按這個庫來重構可測試代碼。謝謝! – Saxman 2010-10-19 14:48:58