为什么Assert.AreEqual(x,y)失败了,而Assert.Are Equal(y,x)却没有';t
本文关键字:Assert 失败 AreEqual 为什么 Are Equal | 更新日期: 2023-09-27 18:20:31
考虑这个结构:
public struct MyNumber
{
private readonly int _value;
public MyNumber(int myNumber)
{
_value = myNumber;
}
public int Value
{
get { return _value; }
}
public override bool Equals(object obj)
{
if (obj is MyNumber)
return this == (MyNumber) obj;
if (obj is int)
return Value == (int)obj;
return false;
}
public override string ToString()
{
return Value.ToString();
}
public static implicit operator int(MyNumber myNumber)
{
return myNumber.Value;
}
public static implicit operator MyNumber(int myNumber)
{
return new MyNumber(myNumber);
}
}
当我在单元测试中这样做时:
Assert.AreEqual(new MyNumber(123), 123);
它是绿色的。
但这次测试失败了:
Assert.AreEqual(123, new MyNumber(123));
为什么会这样?我想这是因为int类决定了等式,而在第一种情况下,我的类决定了它。但我的类可以隐式转换为int
,这难道没有帮助吗?
如何使Assert.AreEqual同时工作?顺便说一下,我正在使用MSTest。
更新
实现IEquatable<int>
或IComparable<int>
没有帮助。
第一个断言将调用MyNumber.Equals
,并且您已经实现了这样一种方式:如果要比较的参数是Int32
并且等于MyNumber
的值,那么它将成功。
第二个断言将调用Int32.Equals
,它将失败,因为要与之比较的参数是Int32
不知道或不理解的MyNumber
。
您不能使第二个单元测试成功,因为您断言Int32
应该等于您的值。不可能是因为它不同。是Int32.Equals
中的代码决定第二个值是否相等。您已经实现了一些可以进行单元测试的强制转换运算符,因此这些断言应该有效:
Assert.AreEqual(123, (int) new MyNumber(123));
Assert.AreEqual((MyNumber) 123, new MyNumber(123));
即使强制转换是由implicit
实现的,它们也不会自动由Assert.AreEquals
调用,因为此方法需要两个类型为Object
的参数,并且您必须像我上面所做的那样显式调用它们。
由于MyNumber.Equals
中的特殊处理,您现在有一个关于等于不可交换的类型,例如MyNumber(123) equals Int32(123)
是true,但Int32(123) equals MyNumber(123)
是false。您应该避免这种情况,因此我建议您删除MyNumber.Equals
中对int的特殊情况处理,而改用在大多数情况下都适用的隐式强制转换。当他们不这样做时,你将不得不做出明确的演员阵容。
引用Object.Equals
:
以下语句对于Equals(Object)方法的所有实现都必须为true。在列表中,x、y和z表示不是null的对象引用。
。。。
x.Equals(y)返回的值与y.Equal(x)相同。
您的Equals
实现打破了这一硬性要求。如果x
不是null
,则无论其类型如何,((object)x).Equals(123)
都必须返回与((object)123).Equals(x)
相同的值。
有很多代码正确地假设,要求两个对象中的哪一个执行比较并不重要。设计你的代码,这样假设就不会失效。
实际上,这意味着必须以这样一种方式设计类,即不会与任何整数类型进行比较,无论您多么喜欢其他类型。
在MyNumber
结构中实现IComparable<int>
,如下所示:
public int CompareTo(int other)
{
return other.CompareTo(Value);
}
这将确保所有断言按预期工作,例如:
Assert.AreEqual(new MyNumber(123), 123);
Assert.AreEqual(123, new MyNumber(123));
Assert.Greater(124, new MyNumber(123));
Assert.Less(124, new MyNumber(125));