2008-10-03 96 views
57

當你們單元測試依賴於app.config文件中的值的應用程序時?您如何測試這些值是否正確讀取以及程序如何對輸入到配置文件中的錯誤值作出反應?使用NUnit測試app.config文件的單元

不得不修改NUnit應用程序的配置文件是荒謬的,但我無法從我想測試的app.config中讀取值。

編輯:我想我應該澄清也許。我並不擔心ConfigurationManager無法讀取這些值,但我擔心測試程序如何對讀取的值做出反應。

回答

41

我通常會隔離外部依賴項,比如在他們自己的外觀類中使用很少的功能讀取配置文件。在測試中,我可以創建這個類的模擬版本,實現並使用它來代替實際的配置文件。你可以創建你自己的樣機,或者使用像moq或rhino mocks這樣的框架。

通過這種方式,您可以輕鬆地使用不同的配置值嘗試您的代碼,而無需編寫首先編寫xml配置文件的複雜測試。讀取配置的代碼通常很簡單,只需要很少的測試。

0

其實,我想我應該做的是創建一個ConfigFileReader類用於我的項目,然後在單元測試工具中僞裝它?

這是通常的事情嗎?

16

可以同時讀取和寫入app.config文件與ConfigurationManager

+2

Ahhh,所以我可以在ConfigurationManager集合中設置值?我一直認爲它是隻讀的。我想這就是我得到的假設:P – Dana 2008-10-03 21:14:32

+3

我剛剛嘗試過,效果很好!例如,`ConfigurationManager.AppSettings [「SomeKey」] =「MockValue」;`。好答案! – 2011-07-29 18:51:54

+0

當我嘗試它確實改變了密鑰的值ü指定,但也刪除值和所有其他鍵:( – Yasser 2014-09-18 06:19:21

1

您可以隨時在包的接口讀入位,並有從配置文件讀取的具體實施。然後,您將使用模擬對象編寫測試,以查看程序如何處理不良值。我個人並不會測試這個特定的實現,因爲這是.NET Framework代碼(我假設 - 希望 - MS已經測試過了)。

0

最簡單的選擇是包裝讀取配置的方法,以便在測試過程中替換值。創建一個用於讀取配置的接口,並將該接口的實現作爲構造函數參數傳遞或作爲屬性設置在對象上(如使用依賴注入/控制的反轉)。在生產環境中,傳入一個真正從配置讀取的實現;在測試環境中,傳遞一個返回已知值的測試實現。

如果您沒有重構可測試性代碼的選項,但仍然需要對其進行測試,Typemock Isolator提供了實際模擬.NET框架配置類的功能,因此您可以說「下一次請求這樣的appSettings值,返回這個已知的值。「

0

我有同樣的問題,

你可以使用NUnit-console.exe C:\路徑1 \ testdll1.dll C:\ PATH2 \ testdll2.dll

這工作得很好,即使如果兩個DLL文件點不同app.configs 前testdll1.dll.config和testdll2.dll.config

,如果你想使用NUnit項目配置和包裝這些兩個DLL那麼有沒有辦法可以有兩個CONFIGS

你必須有project1。配置如果你的Nunit項目是project1.nunit與Project1.nunit位於同一位置。

希望這可以幫助

29

您可以在運行時在您的測試設置中修改您的配置部分。例如:

// setup 
System.Configuration.Configuration config = 
    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
config.Sections.Add("sectionname", new ConfigSectionType()); 
ConfigSectionType section = (ConfigSectionType)config.GetSection("sectionname"); 
section.SomeProperty = "value_you_want_to_test_with"; 
config.Save(ConfigurationSaveMode.Modified); 
ConfigurationManager.RefreshSection("sectionname"); 

// carry out test ... 

你當然可以設置你自己的幫手方法來更優雅地做到這一點。

11

我遇到了與web.config類似的問題....我找到了一個有趣的解決方案。您可以封裝配置讀取功能,例如是這樣的:

public class MyClass { 

public static Func<string, string> 
    GetConfigValue = s => ConfigurationManager.AppSettings[s]; 

//... 

} 

,然後正常使用

string connectionString = MyClass.GetConfigValue("myConfigValue"); 

但在單元測試初始化​​ 「覆蓋」 的功能是這樣的:

MyClass.GetConfigValue = s => s == "myConfigValue" ? "Hi", "string.Empty"; 

更多一點:

http://rogeralsing.com/2009/05/07/the-simplest-form-of-configurable-dependency-injection/

3

更優雅的解決方案是在配置設置本身上使用普通的舊依賴注入。恕我直言,這是比嘲笑配置閱讀類/包裝等更乾淨。

例如,說一個類「天氣」需要一個「ServiceUrl」爲了功能(例如說它調用Web服務來獲取天氣)。 Weather代碼可以允許一些代碼積極進入配置文件以獲取該設置(無論該代碼是否在Weather類中,或者是一個獨立的配置讀取器,可能會根據其他響應進行模擬),Weather類可以允許要注入的設置,可以通過參數傳遞給構造函數,也可以通過屬性設置器注入。這樣,單元測試非常簡單直接,甚至不需要嘲笑。

然後可以使用Inversion of Control(或Dependency Injection)容器注入設置的值,因此Weather類的使用者不需要從某處顯式提供值,因爲它由容器處理。

2

爲我工作:

public static void BasicSetup() 
    { 
    ConnectionStringSettings connectionStringSettings = 
      new ConnectionStringSettings(); 
    connectionStringSettings.Name = "testmasterconnection"; 
    connectionStringSettings.ConnectionString = 
      "server=localhost;user=some;database=some;port=3306;"; 
    ConfigurationManager.ConnectionStrings.Clear(); 
    ConfigurationManager.ConnectionStrings.Add(connectionStringSettings); 
    } 
20

您可以撥打ConfigurationManager.AppSettings來設置特定的單元測試所需的值的設定方法。

[SetUp] 
public void SetUp() 
{ 
    ConfigurationManager.AppSettings.Set("SettingKey" , "SettingValue"); 
    // rest of unit test code follows 
} 

當單元測試運行,那麼它會使用這些值來運行代碼

0

好吧,我只是有同樣的問題... 我想測試從引用的BL項目網站。 但我只想測試BL。因此,在測試項目的預生成事件中,我將app.Config文件複製到bin \ debug文件夾中,並從app.config中引用它們...