2011-11-22 98 views
7

我想測試一段返回對象的代碼。單元測試...如何改進它

我使用NUnit和測試類,我寫來測試我的方法能正常工作的方法...

[Test] 
public void GetMyObjectFromLog() 
{ 
    string _xmlFilePath = @"C:\XmlFile.xml"; 
    MyObjectParser _myObjectParser = new MyObjectParser(); 
    MyObject _mockMyObject = new MyObject 
           { 
            Title = "obj", 
            Name = "objName" 
           } 
    MyObject _myObject = _myObjectParser.GetMyObjectFromLog(_xmlFilePath); 

    Assert.AreEqual(_mockMyObject , _myObject); 
} 

此測試不起作用,因爲MyObject不會覆蓋Equals方法,和我不爲了測試目的,我們不想重寫Equals方法。

所以我重寫這樣的測試:

[Test] 
public void GetMyObjectFromLog() 
{ 
    string _xmlFilePath = @"C:\XmlFile.xml"; 
    MyObjectParser _myObjectParser = new MyObjectParser(); 
    MyObject _myObject = _myObjectParser.GetMyObjectFromLog(_xmlFilePath); 

    Assert.AreEqual("obj", _myObject.Title); 
    Assert.AreEqual("objName", _myObject.Name); 
} 

好,它的工作原理......但這個測試是相關的?此外,還有一個依賴文件。

是否恰當使用模擬框架來代替?以及如何使用它?

謝謝!

+0

其實你comarison可以寫成一行,但它的可讀性差:'Assert.That(myObjectA,Is.EqualTo(myObjectB)。使用((x,y)=> x.Name == y .NAME && x.Title == y.Title 0:1));' – Restuta

回答

1

它是絕對OK到對文件的引用。通常有兩種測試類型:單元測試和集成測試。

集成測試總是與某些文件/數據庫或什麼都相互作用。在你的情況下,你可以通過模擬_myObjectParser.GetMyObjectFromLog來改進測試。

你既可以寫自己嘲笑或使用像rhinomocks的框架。一本很好的nunit/rhinomocks的書是:單元測試的藝術。

一個GetMyObjectFromLog更好的可測試的版本看起來是這樣的:

public MyObject GetMyObjectFromLog(IMyXmlReader reader) 
{ 
    var xmlData = reader.GetData(); 
    //make your object here 
    var obj = new MyObject(xmlData); 
    return obj; 
} 

然後,您可以實現implemments一個接口IMyXmlReader,一個從你的生產代碼的文件讀取2個新的類別,以及一個返回在GetData()上總是一樣的字符串。

然後,您可以使用你的類,它總是返回你的單元測試的靜態字符串。

明白嗎?對不起,我的英文:)

+1

耶穌...爲什麼我要補充的解決方案堆棧溢出如果有一個人總是踢下來?我不喜歡那個 – Grrbrr404

+0

哈哈。他也投了我一票。你試圖幫助,這就是你得到:) –

+0

而這個問題得到3票大聲笑。 –

1

是的,它看起來好像那樣。但是,如果您的主項目中不需要它,則可以在測試項目中覆蓋Equals。例如。通常我會創建將私人和受保護的課程推廣到公共課程的課程。所以你可以自由地擴展你的主要項目,以便簡單地測試你的測試項目。

文件相關性是確定的,只是把這個文件在您的測試套件項目。

0

單元測試的目的是測試代碼的邏輯,你的測試上面做兩件事情: 1.邏輯 2.搜索

我說搜索,因爲你要匹配的對象,你在外部文件中創建。如果你這樣做的話,那麼如果沒有外部文件存在,你的構建將會開始中斷,你不需要這樣做。

解決方案: 創建在旅途中的文件,但不創建一個物理文件,在內存中創建一個文件,然後插入你需要匹配的對象,然後匹配的對象。

這樣這個測試永遠不會中斷。

+0

你爲什麼投下了這個票? –

+1

我沒有低估這一點,但你的回答沒有意義 - 你不能在內存中創建一個文件。文件是一個靜態類。你是說Stream? –

2

關於該文件的依賴(甚至似乎不是在項目!):

你可以重寫_myObjectParser.GetMyObjectFromLog也接受流。然後,您可以將該XML文件添加爲嵌入式資源並從程序集中讀取它。

5

首先,解析器中的方法應該是名稱「解析」而不是「獲取」。其次,如果你不希望對象本身能夠與另一對象進行比較,那麼比較它們就像你一樣(屬性屬性)是完全正確的。但是這可以提取到測試類中的一個輔助方法中。

最後,您並不是真的想要將解析器與文件緊密結合。你只是想解析文本。如果你想包含一個靜態幫助器方法,它也打開一個文件和所有東西,這是你的選擇,但它不應該是一個純粹的實例依賴。

[Test] 
public void ParsesObjectFromXml() 
{ 
    string xmlInput = " ... "; 
    MyObjectXmlParser parser = new MyObjectXmlParser(); 
    MyObject expected = new MyObject() {Title = "obj", Name="objName"}; 

    AssertMyObjectsAreEqual(expected, parser.Parse(xmlInput)); 
} 

private bool AssertMyObjectsAreEqual(MyObject expected, MyObject actual) 
{ 
    Assert.AreEqual(expected.Title, actual.Title); 
    Assert.AreEqual(expected.Name, actual.Name); 
} 

現在,您的班級和您的考試都更加清晰,只有一項責任。