2012-03-27 27 views
0

我有一個引發錯誤消息的事件。單元測試錯誤信息的內容?

在我的一些測試,我訂閱的事件,並聲稱該錯誤信息是不是空的。

[Test] 
public MyMethod_DoBad_ErrorMessageNotEmpty() 
{ 
    var logic = new MyClass(); 

    string ErrorMessage = String.Empty; 

    logic.DisplayError += delegate(string s) 
    { 
     ErrorMessage = s; 
    }; 

    logic.DoItBadly(); 

    Assert.IsFalse(String.IsNullOrWhiteSpace(ErrorMessage)); 

} 

//MyClass 

public void DoItBadly() 
{ 
    //do something naughty but not final 
    DisplayError("Naughty"); 

    //some other problem arises 
    if (1==1) 
    DisplayError("Something else naughty"); 
} 

但是我開始在邊緣的情況下測試,我的新的測試應該不合格,合格,因爲它已經在以前的代碼引發錯誤事件之前,它已得到的地方,我希望它找到。

所以我應該斷言錯誤消息包含一個指定的字符串?

+0

如果你爲你的測試提供了一些代碼,那將會很棒。你的測試是獨立的,還是共享一些數據? – 2012-03-27 16:25:50

+0

他們都是獨立的。 – Jon 2012-03-27 16:27:03

回答

0

我想你應該在不同的測試,同時測試這種情況:

[Test] 
public ShouldRaiseNaughtyErrorWhenDoBadly() 
{ 
    var logic = new MyClass(); 
    string errorMessage = String.Empty; 
    logic.DisplayError += delegate(string s) {errorMessage = s; }; 

    logic.DoItBadly(); 

    Assert.That(errorMessage, Is.EqualTo("Naughty")); 
} 

[Test] 
public ShouldRaiseElseNaughtyErrorWhenDoBadlyWithOtherProblem() 
{ 
    var logic = new MyClass(); 
    string errorMessage = String.Empty; 
    logic.DisplayError += delegate(string s) {errorMessage = s; }; 

    // do something for other problem condition 
    logic.DoItBadly(); 

    Assert.That(errorMessage, Is.EqualTo("Something else naughty")); 
} 

或者,如果你需要檢查,其中提出了兩個錯誤:

[Test] 
public ShouldRaiseBothErrors() 
{ 
    var logic = new MyClass(); 
    List<string> errorMessages = new List<string>(); 
    logic.DisplayError += delegate(string s) {errorMessages.Add(s); }; 

    // do something for other problem condition 
    logic.DoItBadly(); 

    Assert.That(errorMessages.Count, Is.EqualTo(2)); 
    Assert.That(errorMessages[0], Is.EqualTo("Naughty")); 
    Assert.That(errorMessages[1], Is.EqualTo("Something else naughty")); 
} 

UPDATE: 考慮基於事件的性質您的通知,你可以趕上他們,然後尋找一些具體錯誤:

[Test] 
public ShouldRaiseNaughtyErrorWhenDoBadly() 
{ 
    var logic = new MyClass(); 
    List<string> errorMessages = new List<string>(); 
    logic.DisplayError += delegate(string s) { errorMessages.Add(s); };  

    logic.DoItBadly(); 

    Assert.That(errorMessages.Contains("Naughty")); 
} 
2

However I am starting to find in edge case testing that my new tests that should fail, pass because it has raised an error event previously in the code before it has got to where I want it to.

這表明您要麼在測試之間重複使用現有對象,要麼您的測試做得太多。如果你不能幫助,但你要測試的真正操作之前的工作,你可以寫你的測試爲:

// Construct objects 
// Do setup work 
// Check that there's no error message yet 

// Do work you expect to fail 
// Check that there *is* an error message 

當然你可以檢查確切的錯誤消息,但是這是有可能最終耗費時間。如果你使用合理的臨時錯誤報告(不用擔心i18n等),那麼我個人只是檢查是否存在錯誤消息。

+0

問題是我的ErrorMessage變量由DoItBadly中發生的錯誤事件填充,然後它到達我想要測試的代碼行。它沒有重用任何東西。它只是第10行提出了一個錯誤事件,但我想要測試第20行也引發了事件 – Jon 2012-03-27 16:28:51

+0

@Jon:正如我所說,檢查它是否爲*第20行之前是空的。如果您期望之前的錯誤,在調用你真正想測試的方法之前,你需要清除它。 – 2012-03-27 16:32:07

+0

其中一個測試方法是問題 – Jon 2012-03-27 16:32:45

0

理想情況下,你會想孤立和抽象DoItBadly的區域()被污染,出現錯誤消息的錯誤文本,這樣您就可以測試方法的其餘部分沒有問題。

但是,考慮到通常說起來容易做起來難,接下來最好的事情是僅在滿足某些條件時才用s填充ErrorMessage(或者有一個不會填充ErrorMessage的錯誤消息的白名單)。所以如果你只設置了ErrorMessage,如果它不是你認爲「可接受」的錯誤,那麼你的測試應該通過並且你自己的要求應該被滿足。

雖然更妙的是斷言,而不是把你的成功案例沒有負面結果的積極成果。