2011-11-26 21 views
7

我有一個奇怪的行爲,在測試中,我想測試,當作爲參數傳遞null時引發異常。當我運行測試,我從NUnit的獲得:與NUnit,ExpectedException和收益返回的奇怪行爲

System.ArgumentNullException was expected 
    -- Exception doesn't have a stack trace -- 

我的測試:

[Test] 
[ExpectedException(typeof(ArgumentNullException))] 
public void Should_not_retrieve_any_fields_when_file_is_null() 
{ 
    _creator.CreateFields(null); 
} 

我的實現:

public IEnumerable<ImportField> CreateFields(HttpPostedFileBase file) 
{ 
    if (file == null) throw new ArgumentNullException("file"); 

    using (var reader = new StreamReader(file.InputStream)) 
    { 
     var firstLine = reader.ReadLine(); 
     var columns = firstLine.Split(new[] { ',' }); 

     for (var i = 0; i < columns.Length; i++) 
     { 
      yield return new ImportField(columns[i], i); 
     } 
    } 
} 

是否有此行爲的合乎邏輯的解釋,我應該讓我的不同的實施?

回答

7

你得到這種行爲的原因是因爲yield關鍵字。當使用yield時,編譯器將爲其中帶有yield的方法生成一個類。當調用該方法時,控制無條件地返回給調用者。在你的方法中沒有什麼是在需要之前實際執行的。

如果您將使用的語句提取到單獨的方法並返回結果,您的測試將通過。或者你可以在你的測試中將結果存儲到變量中,例如在其上調用「ToList()」。

public IEnumerable<ImportField> CreateFields(HttpPostedFileBase file) 
    { 
     if (file == null) throw new ArgumentNullException("file"); 

     return ExtractFromFile(file); 
    } 

    private IEnumerable<ImportField> ExtractFromFile(HttpPostedFileBase file) 
    { 
     using (var reader = new StreamReader(file.InputStream)) 
     { 
      var firstLine = reader.ReadLine(); 
      var columns = firstLine.Split(new[] { ',' }); 

      for (var i = 0; i < columns.Length; i++) 
      { 
       yield return new ImportField(columns[i], i); 
      } 
     } 
    } 
+0

+1 nice catch !! – sll