2012-04-02 54 views
2

我有一個方法需要圍繞它進行try/catch。這是因爲該方法是從Task調用的。如果拋出異常,線程將結束。我可以使用Task.ContinueWith來處理錯誤,然後在出現錯誤時啓動一個新任務,但try/catch會執行此操作。單元測試是否有例外被捕獲

無論如何,我知道我需要放一個try/catch,但是如何測試異常被捕獲?

我可以做到的一種方法是引發一個接受字符串參數的現有事件,然後在單元測試中測試該字符串是否與我期望的字符串匹配。不知道這是否好,但想知道處理這種情況的最佳方法是什麼。

+0

不要抓。或者拋出異常。 – Zenwalker 2012-04-02 09:50:12

+0

如果您的'Catch'塊沒有處理異常,那麼您的單元測試將無法通過拋出該特定異常,但如果抓住/處理了它,您的測試將通過。不確定是否有任何具體的解決方法。 – Rahul 2012-04-02 09:51:15

+0

斷言異常,那麼測試用例不會失敗。 – Zenwalker 2012-04-02 09:59:34

回答

3

如果你正在做TDD,你應該將小步驟,專注於你的類應該做的事情。這裏是例子。你想打印一些報告。首先(我想你正在向外移動),你設計的課程Report應該通過Printer打印自己(這只是例子)。所以你寫測試:

[Test] 
public void ShouldPrintItself() 
{ 
    Mock<IPrinter> printer = new Mock<IPrinter>();    
    Report report = new Report(printer.Object); 
    report.Text = "foo"; 

    report.Print(); 
    printer.Verify(p => p.Print("foo")); 
} 

然後你寫一些執行report.Print方法。你現在正在設計IPrinter接口。接下來您瞭解打印機有時可能會顯示異常(例如紙張不足)。這是你的情況順便說一句。因此,重命名report.Print方法類似TryPrint,改變第一次測試,並建立新的:

[Test] 
public void ShouldPrint() 
{ 
    Mock<IPrinter> printer = new Mock<IPrinter>();    
    Report report = new Report(printer.Object); 
    report.Text = "foo"; 

    Assert.True(report.TryPrint()); 
    printer.Verify(p => p.Print("foo")); 
} 

[Test] 
public void ShouldNotPrint() 
{ 
    Mock<IPrinter> printer = new Mock<IPrinter>(); 
    printer.Setup(p => p.Print(It.IsAny<string>())).Throws<Exception>(); 
    Report report = new Report(printer.Object); 
    report.Text = "foo"; 

    Assert.False(report.TryPrint()); 
} 

,並返回到TryPrint方法。現在,你周圍添加通話try catch塊打印機,使您的測試通過(同樣,你應該在你的應用程序做):

public bool TryPrint() 
{ 
    try 
    { 
     _printer.Print(_text); 
     return true; 
    } 
    catch (Exception ex) 
    { 
     // of course, log exception 
     return false; 
    }   
} 

當你在這裏做,你可以移動到Printer創作。在你的情況下,它將是組件測試。好消息 - 你已經有了IPrinter界面設計。所以,你寫的測試和驗證,在某些情況下,異常將被拋出:

[Test] 
public void ShouldThrowExceptionWhenNoPaperLeft() 
{ 
    Printer printer = new Printer(); 
    printer.PagesCount = 0; 

    Exception ex = Assert.Throws<Exception>(() => printer.Print("foo")); 
    Assert.That(ex.Message, Is.EqualTo("Out of paper")); 
} 

,當然還有,你寫你的組件實現通過該測試。之後,try catch塊的課程將按預期工作,並且組件按預期工作,並在應有時引發異常。

1

您添加try/catch意味着當被測試的類調用另一個拋出異常時,您有期望的行爲。 try/catch是「如何」,測試行爲。

因此,使用嘲諷,當調用「其他」服務時引發異常並測試您的類是否符合要求。先寫測試,這會讓你覺得你爲什麼要放一個try /漁獲。

+0

我正在做測試。我只知道我需要那個嘗試/抓住那裏。只是不確定我是如何確認它被抓到的。我不能放入其中,然後圍繞另一個創建任務的類嘗試/捕獲,但我認爲我仍然處於相同位置 – Jon 2012-04-02 10:00:35

1

您應該測試什麼您的應用程序實際上是做,而不是如何。所以只是嘲笑你的任務拋出一個異常,並驗證在這種情況下引發了新的任務。

0

這是我已經有,但有興趣的人的意見:

[Test] 
public void DoSomething_NullParameterEntered_ShouldCatchException() 
{ 
    var component = new Whatever(); 

    try 
    { 
     component.DoSomething(null); //If a try/catch block exists it will not fall into the below catch 
    } 
    catch 
    { 
     Assert.Fail(); 
    } 
} 
+0

如果try/catch塊不存在,則無論如何,您的測試都將失敗,因爲異常被拋出。所以,你只需在沒有try/catch的情況下編寫'DoSomething(null)'的測試。而且你編寫了一些測試,希望組件中的異常可以用於'DoSomething(not null)'。看我下面的例子。 – 2012-04-02 22:32:19