2010-01-04 61 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; 
     } 
    }