2016-12-19 66 views
3

想象一下這個簡單的場景:我有一個叫MyModel類:我應該如何在C#中測試多個必填字段?

public class MyModel 
{ 
    public string Prop01 { get; set; } 
    public string Prop02 { get; set; } 
    public string Prop03 { get; set; } 

    public bool IsValid() 
    { 
     if (String.IsNullOrEmpty(Prop01) || String.IsNullOrEmpty(Prop02) || String.IsNullOrEmpty(Prop03)) 
      return false; 

     return true; 
    } 
} 

如,你可以看到,如果有的話就MyModel屬性爲空或爲空,IsValid()方法將返回false,換句話說,所有的字段都是「必需的」。

我寫了一些單元測試測試IsValid()方法:

[TestMethod] 
public void MyModel_Invalid_When_Prop01_Is_Null() 
{ 
    var myModel = new MyModel(); 
    Assert.AreEqual(myModel.IsValid(), false); 
} 

[TestMethod] 
public void MyModel_Invalid_When_Prop02_Is_Null() 
{ 
    var myModel = new MyModel(); 
    Assert.AreEqual(myModel.IsValid(), false); 
} 

[TestMethod] 
public void MyModel_Invalid_When_Prop03_Is_Null() 
{ 
    var myModel = new MyModel(); 
    Assert.AreEqual(myModel.IsValid(), false); 
} 

當然,所有的這些測試會過去,但我不與非常高興。讓我們想象一下,我是看到了MyModel_Invalid_When_Prop01_Is_Null測試(由另一個開發商writen)的開發人員。我期望僅僅通過將值分配給的myModelProp01,試驗應啓動失敗。但是,當然,這不會發生的,所以我改變了測試,如下所示:

[TestMethod] 
public void MyModel_Invalid_When_Prop01_Is_Null() 
{ 
    var myModel = new MyModel(); 
    myModel.Prop02 = "Some value"; 
    myModel.Prop03 = "Some value"; 

    Assert.AreEqual(myModel.IsValid(), false); 
} 

[TestMethod] 
public void MyModel_Invalid_When_Prop02_Is_Null() 
{ 
    var myModel = new MyModel(); 
    myModel.Prop01 = "Some value"; 
    myModel.Prop03 = "Some value"; 

    Assert.AreEqual(myModel.IsValid(), false); 
} 

[TestMethod] 
public void MyModel_Invalid_When_Prop03_Is_Null() 
{ 
    var myModel = new MyModel(); 
    myModel.Prop01 = "Some value"; 
    myModel.Prop02 = "Some value"; 

    Assert.AreEqual(myModel.IsValid(), false); 
} 

現在測試真的測試,每個屬性都被填充了,但如果我添加Prop04MyModel ,這也是必填字段,我需要再次更改所有單元測試,所以我不認爲這是個好主意。

所以我的問題是:我該如何單元測試多個必需的屬性,我確信測試是通過還是失敗,因爲我正在測試的特定屬性?或者,也許,我應該測試這些場景嗎?

回答

5

而是用空的,無效的模型開始的,你可以開始與一個有效的,然後使其無效。這將確保你只需要在一個地方修改你的測試,這很好,因爲你的實際需求發生了變化。

另外一個好處是,你的測試變得更加明確,因爲安裝時明確做出模型無效:

[TestMethod] 
public void MyModel_Invalid_When_Prop01_Is_Null() 
{ 
    var myModel = getValidModel(); 
    myModel.Prop01 = null;  
    Assert.AreEqual(myModel.IsValid(), false); 
} 

[TestMethod] 
public void MyModel_Invalid_When_Prop02_Is_Null() 
{ 
    var myModel = getValidModel(); 
    myModel.Prop02 = null; 

    Assert.AreEqual(myModel.IsValid(), false); 
} 

[TestMethod] 
public void MyModel_Invalid_When_Prop03_Is_Null() 
{ 
    var myModel = getValidModel(); 
    myModel.Prop03 = null; 

    Assert.AreEqual(myModel.IsValid(), false); 
} 

MyModel getValidModel() => 
    new MyModel 
    { 
     Prop01 = "Some value", 
     Prop02 = "Some value", 
     Prop03 = "Some value", 
    }; 

如果模型初始化變得更加複雜,你可以利用該生成器模式的。 我寫了一篇博客,一篇關於這可能是有益的:https://www.kenneth-truyers.net/2013/07/15/flexible-and-expressive-unit-tests-with-the-builder-pattern/

+0

非常好!感謝你的回答! –

+0

很高興幫助! *如果它對你有幫助,請注意/接受答案 – Kenneth

0

在我看來,如果isValid()是足夠重要的是一個方法,那麼它很重要的是,其行爲應進行測試。

在某些方面,它的邏輯的簡單性麻痹你依然能感覺到它不可能是值得所有的工作。好吧,我得到它,但相反的觀點是,如果有人增加了一個必填字段,不能更新isValid()是一個非常合理的錯誤;如果你不測試,如果isValid()的行爲,你不會知道,直到某種神祕的生產臭蟲,沒有人認爲找Prop04爲空,因爲哎,isValid()返回true ...

所以,是的,我d測試它;但是,是的,你可以更容易。您可以在您的測試類中創建一個幫助函數,該函數會生成填充了所有字段的MyModel的虛擬實例。那麼你的測試方法只是看起來像

(請原諒任何代碼拼寫錯誤;我不是在編譯器,但我想你會明白我的意思...)

[TestMethod] 
public void MyModel_Invalid_When_Prop01_Is_Null() 
{ 
    var myModel = getMyModelInstance(); 
    myModel.Prop01 = Null; 

    Assert.AreEqual(myModel.IsValid(), false); 
} 

當然你」 d有另一種測試方法設置任何屬性爲空,並斷言IsValid()應返回true。

所以,現在你添加一個新的屬性,你添加一個新的測試方法(你期望這麼做)。您更新助手以填充新屬性;無論如何,你需要支持「IsValid()是真實的」情況。因此,其他現有的測試方法都不需要更新。