NUnit CollectionAssert.AreEqual(应为,实际)与Assert.IsTTrue(应为.Seq
本文关键字:应为 Assert Seq IsTTrue CollectionAssert AreEqual NUnit 实际 | 更新日期: 2023-09-27 18:26:43
我有一些对象被放入队列中。队列中的所有对象都实现相同的基本接口,这也要求它们实现IEquatable<>。
我想验证队列中是否按正确的顺序放置了正确的对象。
当我编写一个使断言为CollectionAssert.AreEqual(expected,actual)
的测试时,该测试失败,并指出,虽然队列是预期的长度,但它在索引0处不同。
但是,当我将测试断言写成Assert.IsTrue(expected.SequenceEqual(actual))
时,测试就通过了。
在我看来,这两个断言应该是相同的,但显然它们完全不同。
NUnit的网站上并没有非常详细地介绍集合断言方法,而Linq文档虽然更详细,但如果不能与NUnit使用集合断言方法所做的事情进行比较,就没有真正的帮助。
这两个断言有何不同?
编辑-添加详细信息
以下是正在测试的代码以及我希望得到相同结果的两个测试。
public enum ArgumentTypeEnum
{
SpiceworksDbName,
DestinationDbName,
DestinationServerName
}
public interface IArgument : IEquatable<IArgument>
{
}
public interface ICommandArgument : IArgument
{
ArgumentTypeEnum ArgumentType { get; }
}
internal interface IValueArgument : IArgument
{
String ArgumentValue { get; }
}
public class CommandArgument : ICommandArgument
{
public CommandArgument(ArgumentTypeEnum argumentType) {
ArgumentType = argumentType;
}
public ArgumentTypeEnum ArgumentType { get; private set; }
public bool Equals(IArgument other)
{
if (other == null)
{
return false;
}
var otherAsCommandArg = other as CommandArgument;
if (otherAsCommandArg == null)
{
return false;
}
return ArgumentType == otherAsCommandArg.ArgumentType;
}
}
public class ValueArgument : IValueArgument
{
public ValueArgument(String argumentValue)
{
ArgumentValue = argumentValue;
}
public string ArgumentValue { get; private set; }
public bool Equals(IArgument other)
{
if (other == null)
{
return false;
}
var otherAsValueArg = other as ValueArgument;
if (otherAsValueArg == null)
{
return false;
}
return ArgumentValue == otherAsValueArg.ArgumentValue;
}
}
public class Tokenizer
{
public Queue<IArgument> TokenizeArguments(string[] args) {
var tokenQueue = new Queue<IArgument>();
args.ToList().ForEach((arg) => {
if (arg.StartsWith("-"))
{
switch (arg)
{
case "-sd":
tokenQueue.Enqueue(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName));
break;
case "-dd":
tokenQueue.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationDbName));
break;
case "-ds":
tokenQueue.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationServerName));
break;
default:
tokenQueue.Enqueue(new ValueArgument(arg));
break;
}
}
else
{
tokenQueue.Enqueue(new ValueArgument(arg));
}
});
return tokenQueue;
}
}
[TestFixture]
public class TokenizerSpecs
{
///Passes
[Test]
public void Tokenizer_MultipleCommandsAndValues_TokenizesAsExpected1() {
var args = new[]
{
"-sd", @"''some'Directory'foo.db", "-dd", "some database name", "-ds", "Server.name", "somerandomarg",
"-unreconized"
};
var t = new Tokenizer();
var actualResult = t.TokenizeArguments(args);
var expectedResult = new Queue<IArgument>();
expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName));
expectedResult.Enqueue(new ValueArgument(@"''some'Directory'foo.db"));
expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationDbName));
expectedResult.Enqueue(new ValueArgument("some database name"));
expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationServerName));
expectedResult.Enqueue(new ValueArgument("Server.name"));
expectedResult.Enqueue(new ValueArgument("somerandomarg"));
expectedResult.Enqueue(new ValueArgument("-unreconized"));
Assert.IsTrue(expectedResult.SequenceEqual(actualResult));
}
///Fails
[Test]
public void Tokenizer_MultipleCommandsAndValues_TokenizesAsExpected2()
{
var args = new[]
{
"-sd", @"''some'Directory'foo.db", "-dd", "some database name", "-ds", "Server.name", "somerandomarg",
"-unreconized"
};
var t = new Tokenizer();
var actualResult = t.TokenizeArguments(args);
var expectedResult = new Queue<IArgument>();
expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName));
expectedResult.Enqueue(new ValueArgument(@"''some'Directory'foo.db"));
expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationDbName));
expectedResult.Enqueue(new ValueArgument("some database name"));
expectedResult.Enqueue(new CommandArgument(ArgumentTypeEnum.DestinationServerName));
expectedResult.Enqueue(new ValueArgument("Server.name"));
expectedResult.Enqueue(new ValueArgument("somerandomarg"));
expectedResult.Enqueue(new ValueArgument("-unreconized"));
CollectionAssert.AreEqual(expectedResult, actualResult);
}
}
我看了NUnit的源代码,这里似乎有一个bug。由CCD_ 3进行比较,CCD_。我们可以使用这个对象进行简单的测试:
var n = new NUnitEqualityComparer();
var tolerance = Tolerance.Zero;
var equal = n.AreEqual(new CommandArgument(ArgumentTypeEnum.SpiceworksDbName),
new CommandArgument(ArgumentTypeEnum.SpiceworksDbName),
ref tolerance);
此测试返回false
!
不知怎的,ObjectsEqual
最终不会出现在对象的Equals
方法中。这需要对源代码进行调试才能找出原因,但这次测试充分证明了其中存在漏洞。