2012-02-23 75 views
51

我正在爲這個返回「void」的方法寫一個單元測試。我希望在沒有異常拋出時測試通過一個案例。我如何在C#中編寫?C#:如何在我的單元測試中檢查「沒有發生異常」?

Assert.IsTrue(????) 

(我的猜測是,這是我應該怎麼檢查,但什麼進入「???」)

我希望我的問題是非常明顯的。

+0

您使用的是MSTest還是NUnit? – 2012-02-23 16:41:22

+2

在MSTest中,未捕獲的異常會自動導致測試失敗。你是否試圖解釋捕獲的異常? – Phil 2012-02-23 16:42:04

+0

您可以查看「try-catch for C#」,這將指導您如何處理拋出或不拋出的異常。 – Foggzie 2012-02-23 16:42:14

回答

81

如果拋出異常,你的單元測試將會失敗 - 你不需要放置一個特殊的斷言。

這是少數情況下你會看到沒有斷言的單元測試之一 - 如果引發異常,測試將隱式失敗。

但是,如果你真的想要寫這個斷言 - 也許能夠捕獲異常,並報告「預計也不例外,但得到這個......」,你可以這樣做:

[Test] 
public void TestNoExceptionIsThrownByMethodUnderTest() 
{ 
    var myObject = new MyObject(); 

    try 
    { 
     myObject.MethodUnderTest(); 
    } 
    catch (Exception ex) 
    { 
     Assert.Fail("Expected no exception, but got: " + ex.Message); 
    } 
} 

(以上是NUnit的示例,但對於MSTest也是如此)

+0

顯然,你不應該去抓這些例外,以保持真實。 – Servy 2012-02-23 16:42:10

+5

只有在引發未捕獲的異常時,測試纔會失敗。取決於異常處理程序中的代碼,單元測試可能會通過。 – ediblecode 2012-02-23 16:43:05

9

不要測試那些東西doesn't happen。這就像確保代碼不會中斷。這是暗示的,我們都努力爭取不間斷的,無缺陷的代碼。你想爲它寫測試嗎?爲什麼只有一種方法?難道你不想讓你的所有方法都被測試:他們不要拋出一些異常?在此之後,您將以代碼庫中的每種方法結束一個額外的虛擬測試,斷言測試。它沒有帶來任何價值。

當然,如果您的要求是驗證方法確實捕獲異常,你測試(或逆轉了一點,測試,它不會引發什麼是應該抓)。

但是,一般方法/實踐保持不變 - 您不會爲某些超出測試代碼範圍的人爲/模糊需求編寫測試(並且測試「有效」或「不會丟失」是通常是這樣的一個例子 - 特別是在方法的責任衆所周知的情況下)。

說得簡單 - 專注於你的代碼必須做的並測試。

+4

-1我可以想到積極的功能,需要和異常不會被拋出。對於處理異常的單一方法,記錄它們並採取行動 - 而不會進一步拋出異常。你提出了一個很好的總體觀點 - 然後在_absolute_中說話,就好像它總是如此。 – 2012-02-23 20:19:51

+0

@RobLevine:當你的例子在記錄時拋出會發生什麼?你是否斷言它並沒有對此進行測試?這是我的全部觀點。我並不是想要聽起來「宗教」(我也不理解downvote的理由),但斷言某些事情沒有發生*,總的來說,這很**適得其反。你通常想要相反,斷言你的代碼*做某事*。這很簡單。 – 2012-02-24 01:43:30

+0

我明白你的意思 - 這是很好的_通用建議。麻煩的是,從絕對開始的那一刻,就會損害核心點。如果被測代碼的性質是_prevent_拋出異常,那麼這是一個_positive_斷言,以確保沒有拋出異常。在一般情況下,你的整體觀點是好的,但我認爲這是你設計它的方式,這讓我覺得它總體上是無益的建議。 -1有點嚴厲 - 幾分鐘後我改變了主意,但除非您再次編輯帖子,否則它不會讓我+1。對於那個很抱歉。 – 2012-02-24 10:13:07

16

在NUnit的,你可以使用:

Assert.DoesNotThrow(<expression>); 

斷言,您的代碼不會拋出異常。雖然如果即使周圍沒有Assert也會拋出異常,測試會失敗,但這種方法的價值在於,您可以區分未滿足的期望和測試中的錯誤,並且您可以選擇添加自定義消息將顯示在您的測試輸出中。措辭良好的測試輸出可以幫助您找到代碼中導致測試失敗的錯誤。

我認爲這是有效的添加測試,以確保您的代碼不引發異常;例如,假設您正在驗證輸入並需要將傳入的字符串轉換爲長整型。有時可能會出現字符串爲空的情況,這是可以接受的,所以您希望確保字符串轉換不會引發異常。因此將會有代碼來處理這種情況,如果你沒有爲它寫一個測試,你將錯過圍繞一個重要邏輯的覆蓋。

+1

明確的DoesNotThrow很好。如果你習慣在測試中看到Assert。*,你可能會認爲另一個人很懶,並且忘記了。 – 2014-06-11 18:04:12

+0

在vstest或mstest中是否有任何等價物? – 2015-03-12 18:40:20

+1

@DanCsharpster,我不認爲至少在MSTest中 - 當我在過去需要MSTest中的這個功能時,我做了這樣的事情: 'public class TestBase { // believe我,我不喜歡這個,比你更喜歡。 保護無效AssertDoesNotThrow(動作動作,字符串消息) { 嘗試 { action(); (例外) } catch(例外) Assert.Fail(message); } } }' – Clarkeye 2015-03-27 11:19:49

3

這個幫助類使用MSTest來抓我的癢。也許它也可以抓你的。

[TestMethod] 
public void ScheduleItsIneligibilityJob_HasValid_CronSchedule() 
{ 
    // Arrange 
    var factory = new StdSchedulerFactory(); 
    IScheduler scheduler = factory.GetScheduler(); 

    // Assert 
    AssertEx.NoExceptionThrown<FormatException>(() => 
     // Act 
     _service.ScheduleJob(scheduler) 
    ); 
} 

public sealed class AssertEx 
{ 
    public static void NoExceptionThrown<T>(Action a) where T:Exception 
    { 
     try 
     { 
      a(); 
     } 
     catch (T) 
     { 
      Assert.Fail("Expected no {0} to be thrown", typeof(T).Name); 
     } 
    } 
} 
1

我最喜歡看的Assert.Whatever在每次測試結束,只爲一致性......沒有一個,我真的能確定自己不應該是一個人也沒有?

對於我來說,這是把Assert.IsTrue(true);

簡單我知道我沒有意外把這些代碼在那裏,因此我應該在一個快速通過,這是脫脂有足夠的自信如預期。

[TestMethod] 
    public void ProjectRejectsGappedVersioningByDefault() { 

     var files = new List<ScriptFile>(); 
     files.Add(ScriptProjectTestMocks.GetVersion1to2()); 
     files.Add(ScriptProjectTestMocks.GetVersion3to4()); 

     Assert.Throws<ScriptProject.InvalidProjectFormatException>(() => { 
      var sut = new ScriptProject(files); 
     }); 

    } 

    [TestMethod] 
    public void ProjectAcceptsGappedVersionsExplicitly() { 

     var files = new List<ScriptFile>(); 
     files.Add(ScriptProjectTestMocks.GetVersion1to2()); 
     files.Add(ScriptProjectTestMocks.GetVersion3to4()); 

     var sut = new ScriptProject(files, true); 

     Assert.IsTrue(true); // Assert.Pass() would be nicer... build it in if you like 

    } 
相關問題