2013-04-18 32 views
3

我正在通過我們的應用程序的單元測試,並改進/添加更多。我很(不,很)新手在單元測試/測試驅動開發,我發現了以下方法,我想測試。我被卡住了,我的問題是如果有一種方法來重寫這個,以便它是可測試的?重寫操作系統查詢方法變得可測試

public static bool Is32BitOS() 
{ 
     string os = (from x in new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem").Get().OfType<ManagementObject>() 
        select x.GetPropertyValue("Caption")).First().ToString().Trim(); 

     if (os.Equals("Microsoft Windows XP Professional")) 
     { 
      return true; 
     } 

     if (os.StartsWith("Microsoft Windows 7")) 
     { 
      string architecture = (from x in new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem").Get().OfType<ManagementObject>() 
            select x.GetPropertyValue("OSArchitecture")).First().ToString(); 
      if (architecture == "64-bit") 
      { 
       return false; 
      } 
     } 

     return true; 
} 
+2

您可以隨時換行'ManagementObjectSearcher'在瘦界面,這將自動讓你的依賴清晰可見,並可以輕鬆地用於其他實現,例如測試...只是一個想法(我在電話中,所以它很簡短;)) –

+2

如果您使用的是.NET 4.0,請查看'Environment.Is64BitOperatingSystem()'方法http://msdn.microsoft.com/ en-us/library/system.environment.is64bitoperatingsystem%28VS.100%29.aspx – bniwredyc

+0

檢查[此問題](http://stackoverflow.com/q/336633/706456) – oleksii

回答

2

你的方法有3個職責:

  1. 管理對象搜索創建
  2. 操作系統和架構檢索
  3. 操作系統驗證

爲了使測試我的程序集信息添加.cs與此類似的行:

[assembly: InternalsVisibleTo("Your.Test.Project")] 

這樣受保護的方法對測試項目可見,但對客戶端不可用。 然後使該操作系統驗證分開後,我已經重寫你的方法:

//Acceptance test this method 
public static bool Is32BitOS() 
{ 
    var managementObjects = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem").Get().OfType<ManagementObject>(); 

    string os = (from x in managementObjects select x.GetPropertyValue("Caption")).First().ToString().Trim(); 
    string architecture = (from x in managementObjects select x.GetPropertyValue("OSArchitecture")).First().ToString(); 

    return Is32BitOS(os, architecture); 
} 

//Unit test this method 
internal static bool Is32BitOS(string os, string architecture) 
{ 
    if (os.Equals("Microsoft Windows XP Professional")) 
    { 
     return true; 
    } 

    if (os.StartsWith("Microsoft Windows 7")) 
    { 
     string architecture = archRetriever(); 
     if (architecture == "64-bit") 
     { 
      return false; 
     } 
    } 
    return true; 
} 

現在我們已經分開的擔憂我會說,你的單元測試應該只驗證Is32BitOs行爲,同時驗收測試應當驗證端到端堆棧。 事實上,你有單元測試的小值

(from x in new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem").Get().OfType<ManagementObject>() 
select x.GetPropertyValue("Caption")).First().ToString().Trim(); 

,而你真正的價值在於這些信息的使用情況,以確定如果操作系統是32位檢索OS字符串。

另一種在接口中封裝並使用嘲諷框架的方法是應用函數式編程看看here for Llewellyn Falco's peel and slice techniquehere Arlo Belshee's no mocks approach。因此,而不是一個方法,如:

public static bool Is32BitOS(IRetrieveOsAndArchitecture roa) 
{ 
    string os = roa.GetOs();     
    string architecture = roa.GetArchitecure(); 

    return Is32BitOS(os, architecture); 
} 

您可以使用類似:

public static bool Is32BitOS(Func<ManagementObjectSearcher, string> osRetriever, 
          Func<ManagementObjectSearcher, string> archRetriever, 
          ManagementObjectSearcher searcher) 
{ 
    string os = osRetriever(searcher);    
    string architecture = archRetriever(searcher); 

    return Is32BitOS(os, architecture); 
} 

其客戶端的方法是:

public static bool Is32BitOS() 
{ 
    var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem"); 

    return Is32Bit((s)=>{ (from x in s.Get().OfType<ManagementObject>() select x.GetPropertyValue("Caption")).First().ToString().Trim()}, 
        (s)=>{ (from x in s.Get().OfType<ManagementObject>() select x.GetPropertyValue("OSArchitecture")).First().ToString();}, 
        searcher); 
} 

注意,在測試的接口和功能的情況下,你沒有使用真正的ManagementObjectSearcher外部依賴;在mockist方法中,您將在函數式編程中使用模擬對象,您將傳遞不同的lambda表達式,該lambda表達式應只返回os和體系結構字符串。

這個方法還有一個責任,就是創建ManagementObjectSearcher;要解決這種依賴關係,您可以:

  1. 將它作爲方法的參數
  2. 使其在構建時initilized類的領域