Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#单元测试中的双向列表比较_C#_Unit Testing_Coding Style_Readability - Fatal编程技术网

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

C#单元测试中的双向列表比较,c#,unit-testing,coding-style,readability,C#,Unit Testing,Coding Style,Readability,在我的C#单元测试中,我经常根据ID列表查询行列表。然后我想确保1)对于所有ID,至少找到一行具有该ID;2)对于所有返回的行,每行都有一个ID,该ID位于要查找的ID列表中。以下是我通常如何确保: Assert.IsTrue(ids.All( id => results.Any(result => result[primaryKey].Equals(id)) ), "Not all IDs were found in returned results"); Assert.

在我的C#单元测试中,我经常根据ID列表查询行列表。然后我想确保1)对于所有ID,至少找到一行具有该ID;2)对于所有返回的行,每行都有一个ID,该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");
我认为使用
Any
All
对这样的检查很方便,但我想看看是否有人认为这样做的可读性不如它,或者是否有更好的方法进行这样的双向检查。我正在VisualStudio2008团队系统中使用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()
);

在国际海事组织,它的可读性不如它所能。创建并记录一个返回true/false的方法。然后调用Assert.IsTrue(methodWithDescriptiveNameWhichReturnsTrueOrfalse(),“失败原因”)

您可以选择使用
除了
操作符:

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

NUnit有
CollectionAssert
断言系列,有助于可读性。

下面是我为处理两个可枚举项而编写的代码片段,在MS test中执行单元测试时引发异常,这可能会有所帮助:

使用

比较两个可枚举项:

 MyAssert.AreEnumerableSame(expected,actual);
管理异常

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

公共类MyAssert
{
公共类资产管理员
{
公共bool成功{get;set;}
公共字符串消息{get;set;}
}
公共静态void抛出(Action Action,string expectedMessage),其中T:Exception
{
AssertAnswer-answer=AssertAction(操作、预期消息);
断言.是真的(回答.成功);
Assert.AreEqual(expectedMessage、answer.Message);
}
公共静态void AreEnumerableName(IEnumerable enumerable1,IEnumerable enumerable2)
{
bool isSameEnumerable=true;
布尔·伊萨默特;
如果(enumerable1.Count()==enumerable2.Count())
{
foreach(enumerable1中的对象o1)
{
isSameObject=false;
foreach(enumerable2中的对象o2)
{
如果(o2等于(o1))
{
isSameObject=true;
打破
}
}
如果(!isSameObject)
{
isSameEnumerable=false;
打破
}
}
}
其他的
isSameEnumerable=false;
Assert.IsTrue(isSameEnumerable);
}
公共静态AssertAnswer AssertAction(Action Action,string expectedMessage),其中T:Exception
{
AssertAnswer answer=新AssertAnswer();
尝试
{
action.Invoke();
回答:成功=错误;
Message=string.Format(“应该抛出类型{0}的异常。”,typeof(T));
}
捕获(T exc)
{
回答:成功=正确;
应答。消息=预期消息;
}
捕获(例外e)
{
回答:成功=错误;
answer.Message=string.Format(“抛出了一个不同的异常{0}.”,e.GetType());
}
返回答案;
}
}

这看起来不错,我喜欢只写一次
x[primaryKey]
。但是,我认为应该是
Count()==0
,考虑到如何描述
除了
。实际上,您需要保留>0,但交换消息。修改了我的答案。为什么需要
>0
?我希望检索到的结果ID列表和我查询的ID列表之间没有区别。Intellisense将
除了
描述为产生“两个序列的集差”。比
Count()==0
更好的替代方法是
Any()
。我没有使用
Count()==0
Any()
,而是使用
Assert.AreEqual
Count()
0
+1这本质上是自定义断言xUnit测试模式,不过您也可以将其设置为void方法并将断言移动到方法中。
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;
        }
    }