2014-11-21 11 views
2

我正在與另一位開發人員開發一個開源項目。我正在研究需要讀取默認自定義xml配置文件的單元測試。我只能保證回購中的路徑部分將在他的機器上。我怎樣才能重寫這個測試,使其可移植?我不希望測試每次檢查代碼時都會出現失敗。單元測試需要讀取文件。我如何使它便攜?

public class ConfigurationTests 
{ 
    [TestMethod] 
    public void ConfigurationLoads() 
    { 
     //todo: how do I make this test portable? 
     const string configFile = @"C:\Users\Christopher\Source\Repos\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config"; 
     var deserializer = new XmlSerializer(typeof(Rubberduck.Config.Configuration)); 
     using (StreamReader reader = new StreamReader(configFile)) 
     { 
      Rubberduck.Config.Configuration config = (Rubberduck.Config.Configuration)deserializer.Deserialize(reader); 
      Assert.IsNotNull(config); 
     } 
    } 
} 

這是我保證其他開發者將擁有的路徑的一部分。在此之前,我需要以某種方式動態獲取。

\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config 
+0

據我所知,單元測試不應該依賴於系統外部的任何東西 - 正是因爲配置不能保證是可移植的。 – Gigi 2014-11-21 13:04:25

+0

這個'TestMethod'應該測試什麼?現在,它只測試'XmlSerializer.Deserialize'返回'Rubberduck.Config.Configuration'的實例......但你不是'XmlSerializer'的作者,所以測試它是沒有意義的。 – 2014-11-21 13:04:37

+0

對。這就是我問的原因。你如何建議我重寫我的測試,以便我不依賴文件?我是單元測試新手,所以我不知道在這裏做什麼@Gigi。 – RubberDuck 2014-11-21 13:07:47

回答

3

你應該做的是創建一個接口到一個文件系統,並在測試嘲笑它。訪問真實文件系統的這個接口的實現你不能測試,所以它必須儘可能簡單。由於XmlSerializer.Deserialize方法接受Stream,因此您的接口可以返回Stream。

public interface IFileAccess 
{ 
    Stream GetFileStream(string fileName); 
} 

public class RealFileAccess : IFileAccess 
{ 
    public Stream GetFileStream(string fileName) 
    { 
      .... 
    } 
} 

public class ConfigLoader 
{ 
    Rubberduck.Config.Configuration LoadConfiguration(IFileAccess fileAccess) 
    { 
      const string configFile = @"C:\Users\Christopher\Source\Repos\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config"; 
      var deserializer = new XmlSerializer(typeof(Rubberduck.Config.Configuration)); 
     return (Rubberduck.Config.Configuration)deserializer.Deserialize(fileAccess.GetFileStream(configFile)); 
    } 
} 

然後測試將

[TestMethod] 
public void ConfigurationLoads() 
{ 
    const string configFile = @"C:\Users\Christopher\Source\Repos\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config"; 
    IFileAccess fileAccess = Mock.Of<IFileAccess>(); 
    // setup fileAccess 
    Rubberduck.Config.Configuration config = new ConfigLoader().LoadConfiguration(fileAccess); 
    Assert.IsNotNull(config); 
    Mock.Get(fileAccess).Verify(fa => fa.GetFileStream(configFile)); 
} 

然後,您可以甚至是否GetFileStream用正確的參數調用。

+0

非常感謝。這是我需要看到的。我會稍後再嘗試。你可能想從你的答案中刪除'const string configFile ...'行。這條路線不再需要。 – RubberDuck 2014-11-21 13:28:00

+1

我將它留在那裏,以便您可以聲明它在GetFileStream調用中使用。我將添加斷言。 – 2014-11-21 13:41:42

2

我的工作需要在一個默認的自定義XML配置文件讀取單元測試。

以上強烈表明它不是真正的單元測試。他們(理想上)獨立於外部世界。 爲什麼你需要讀取配置文件?什麼信息存儲在配置中?也許可以使用測試將帶有虛擬信息的配置文件添加到項目中,或者使用某個接口將依賴項存儲到文件系統。

的標準方法這樣做看起來就像

interface IConfigReader{ 
    object GetValue(string key); 
} 

// later in code 
var configDate = _reader.GetValue("ConnectionString"); 
相關問題