C#单元测试中的双向列表比较

5
在我的C#单元测试中,我经常根据ID列表查询一组行。然后我想确保:1)对于所有的ID,至少找到了一个具有该ID的行;2)对于返回的所有行,每个行都有一个在要查找的ID列表中的ID。这是我通常使用的方法:
Assert.IsTrue(ids.All(
    id => results.Any(result => result[primaryKey].Equals(id))
), "Not all IDs were found in returned results");

Assert.IsTrue(results.All(
    result => ids.Any(id => result[primaryKey].Equals(id))
), "Returned results had unexpected IDs");

我认为使用AnyAll对于这种检查很方便,但我想知道是否有人认为这可能不够易读,或者是否有更好的方式来做类似的双向检查。我在使用Visual Studio 2008 Team System中的MSTest进行单元测试。如果这太主观了,那么这可能应该是社区维基。 编辑: 我现在正在使用基于Aviad 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个回答

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");

这看起来很不错,我喜欢我只需要一次写x [primaryKey]的方式。然而,鉴于Except的描述,我认为它应该是Count() == 0 - Sarah Vessels
实际上,你需要保留 >0,但交换消息的位置。我修改了我的答案。 - Aviad P.
为什么需要使用>0?我期望检索到的结果ID列表和我查询的ID列表没有区别。Intellisense将Except描述为生成“两个序列的集合差异”。 - Sarah Vessels
2
Any()是比Count() == 0更好的选择。 - Mark Seemann
我最终使用Assert.AreEqualCount()0,而不是使用Count() == 0Any() - Sarah Vessels

3

在我看来,这段文本的可读性还有提高的空间。需要创建并记录一个方法,该方法返回true或false。然后调用Assert.IsTrue(methodWithDescriptiveNameWhichReturnsTrueOrfalse(), "reason for failure");


2
这实际上是 自定义断言 xUnit 测试模式,尽管您也可以将其作为 void 方法并将断言移入该方法中。 - Mark Seemann

1
这是我写的一段代码片段,用于处理两个可枚举对象,在进行 MS Test 单元测试时抛出异常。它可能会有所帮助:
使用方法:
比较两个可枚举对象:
 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;
        }
    }

0
NUnit拥有CollectionAssert断言系列,有助于提高可读性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接