2010-01-04 57 views
5

在我的C#單元測試中,我經常查詢基於ID列表的行列表。然後,我想確保1)對於所有ID,至少有一行具有該ID,2)對於所有返回的行,每行都有一個ID,該ID位於要查找的ID列表中。這裏是我通常確保:C#單元測試中的雙向列表比較

我覺得用AnyAll方便這種檢查,但我想看看是否有人認爲,這是不易閱讀比它可能是,或有也許這是一種更好的雙向檢查方式。我在Visual Studio 2008 Team System中使用MSTest進行單元測試。這可能應該是社區wiki,如果它太主觀。

編輯:現在我正使用基於阿維亞德P.的建議的解決方案,同時又有以下測試通過的事實

string[] ids1 = { "a", "b", "c" }; 
string[] ids2 = { "b", "c", "d", "e" }; 
string[] ids3 = { "c", "a", "b" }; 
Assert.AreEqual(
    1, 
    ids1.Except(ids2).Count() 
); 
Assert.AreEqual(
    2, 
    ids2.Except(ids1).Count() 
); 
Assert.AreEqual(
    0, 
    ids1.Except(ids3).Count() 
); 

回答

4

您可以選擇使用Except操作:

var resultIds = results.Select(x => x[primaryKey]); 

Assert.IsTrue(resultIds.Except(ids).Count() == 0, 
"Returned results had unexpected IDs"); 

Assert.IsTrue(ids.Except(resultIds).Count() == 0, 
"Not all IDs were found in returned results"); 
+0

這看起來不錯,我喜歡我只寫一次'x [primaryKey]'。不過,考慮到如何描述Except,我認爲它應該是Count()== 0。 – 2010-01-04 20:09:01

+0

實際上,您需要保持> 0,但交換消息。修改我的答案。 – 2010-01-04 20:10:40

+0

爲什麼你需要'> 0'?我希望在檢索到的結果ID列表和我查詢的ID列表之間沒有區別。智能感知將「Except」描述爲產生「兩個序列的集合差異」。 – 2010-01-04 20:18:41

3

IMO,還不如讀,因爲它可以。創建並記錄一個返回true/false的方法。然後調用Assert.IsTrue(methodWithDescriptiveNameWhichReturnsTrueOrfalse(),「失敗原因」);

+2

+1這實質上就是* Custom Assertion * xUnit Test Pattern,儘管你也可以使它成爲一個void方法並將斷言移入方法中。 – 2010-01-04 20:13:19

0

NUnit的有CollectionAssert家庭斷言,幫助可讀性。

1

這裏的代碼片段我做處理兩個可枚舉,並拋出異常,而做單元測試MS測試,它可能會幫助:

使用

比較兩個可枚舉:

MyAssert.AreEnumerableSame(expected,actual); 

管理異常

MyAssert.Throws<KeyNotFoundException>(() => repository.GetById(1), string.Empty); 

代碼

public class MyAssert 
    { 
     public class AssertAnswer 
     { 
      public bool Success { get; set; } 
      public string Message { get; set; } 
     } 

     public static void Throws<T>(Action action, string expectedMessage) where T : Exception 
     { 
      AssertAnswer answer = AssertAction<T>(action, expectedMessage); 

      Assert.IsTrue(answer.Success); 
      Assert.AreEqual(expectedMessage, answer.Message); 
     } 

     public static void AreEnumerableSame(IEnumerable<object> enumerable1, IEnumerable<object> enumerable2) 
     { 
      bool isSameEnumerable = true; 
      bool isSameObject ; 

      if (enumerable1.Count() == enumerable2.Count()) 
      { 
       foreach (object o1 in enumerable1) 
       { 
        isSameObject = false; 
        foreach (object o2 in enumerable2) 
        { 
         if (o2.Equals(o1)) 
         { 
          isSameObject = true; 
          break; 
         } 
        } 
        if (!isSameObject) 
        { 
         isSameEnumerable = false; 
         break; 
        } 
       } 
      } 
      else 
       isSameEnumerable = false; 

      Assert.IsTrue(isSameEnumerable); 
     } 

     public static AssertAnswer AssertAction<T>(Action action, string expectedMessage) where T : Exception 
     { 
      AssertAnswer answer = new AssertAnswer(); 

      try 
      { 
       action.Invoke(); 

       answer.Success = false; 
       answer.Message = string.Format("Exception of type {0} should be thrown.", typeof(T)); 
      } 
      catch (T exc) 
      { 
       answer.Success = true; 
       answer.Message = expectedMessage; 
      } 
      catch (Exception e) 
      { 
       answer.Success = false; 
       answer.Message = string.Format("A different Exception was thrown {0}.", e.GetType()); 
      } 

      return answer; 
     } 
    }