xUnit 之 Equal(1)

Equal恐怕是写xUnit测试使用最多的方法。那么Equal方法到底能进行哪些类型参数的比较呢?

我们首先看一下Equal方法的几种重载形式:

1. 最常用到的一种形式:

/// <summary>
/// Verifies that two objects are equal, using a default comparer.
/// </summary>
/// <typeparam name="T">The type of the objects to be compared</typeparam>
/// <param name="expected">The expected value</param>
/// <param name="actual">The value to be compared against</param>
/// <exception cref="EqualException">Thrown when the objects are not equal</exception>
public static void Equal<T>(T expected, T actual)

2.带有比较器的Equal方法

/// <summary>
/// Verifies that two objects are equal, using a custom equatable comparer.
/// </summary>
/// <typeparam name="T">The type of the objects to be compared</typeparam>
/// <param name="expected">The expected value</param>
/// <param name="actual">The value to be compared against</param>
/// <param name="comparer">The comparer used to compare the two objects</param>
/// <exception cref="EqualException">Thrown when the objects are not equal</exception>
[SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "If you pass null here, you deserve the NullReferenceException.")]
public static void Equal<T>(T expected, T actual, IEqualityComparer<T> comparer)
 
3.带精度的数值比较
/// <summary>
/// Verifies that two double values are equal, within the number of decimal
/// places given by precision.
/// </summary>
/// <param name="expected">The expected value</param>
/// <param name="actual">The value to be compared against</param>
/// <param name="precision">The number of decimal places (valid values: 0-15)</param>
/// <exception cref="EqualException">Thrown when the values are not equal</exception>
public static void Equal(double expected, double actual, int precision)
以及
/// <summary>
/// Verifies that two decimal values are equal, within the number of decimal
/// places given by precision.
/// </summary>
/// <param name="expected">The expected value</param>
/// <param name="actual">The value to be compared against</param>
/// <param name="precision">The number of decimal places (valid values: 0-15)</param>
/// <exception cref="EqualException">Thrown when the values are not equal</exception>
public static void Equal(decimal expected, decimal actual, int precision)
 
在第一种形式中,提到用的是默认的比较器。那么,xUnit为我们提供的默认的比较器是什么样子的呢?
下面是xUnit相等比较器的代码,非常好懂:
class AssertEqualityComparer<T> : IEqualityComparer<T>
{
static AssertEqualityComparer<object> innerComparer = new AssertEqualityComparer<object>();

public bool Equals(T x, T y)
{
Type type = typeof(T);

// Null?
if (!type.IsValueType || (type.IsGenericType && type.GetGenericTypeDefinition().IsAssignableFrom(typeof(Nullable<>))))
{
if (Object.Equals(x, default(T)))
return Object.Equals(y, default(T));

if (Object.Equals(y, default(T)))
return false;
}

// Same type?
if (x.GetType() != y.GetType())
return false;

// Implements IEquatable<T>?
IEquatable<T> equatable = x as IEquatable<T>;
if (equatable != null)
return equatable.Equals(y);

// Implements IComparable<T>?
IComparable<T> comparable1 = x as IComparable<T>;
if (comparable1 != null)
return comparable1.CompareTo(y) == 0;

// Implements IComparable?
IComparable comparable2 = x as IComparable;
if (comparable2 != null)
return comparable2.CompareTo(y) == 0;

// Enumerable?
IEnumerable enumerableX = x as IEnumerable;
IEnumerable enumerableY = y as IEnumerable;

if (enumerableX != null && enumerableY != null)
{
IEnumerator enumeratorX = enumerableX.GetEnumerator();
IEnumerator enumeratorY = enumerableY.GetEnumerator();

while (true)
{
bool hasNextX = enumeratorX.MoveNext();
bool hasNextY = enumeratorY.MoveNext();

if (!hasNextX || !hasNextY)
return (hasNextX == hasNextY);

if (!innerComparer.Equals(enumeratorX.Current, enumeratorY.Current))
return false;
}
}

// Last case, rely on Object.Equals
return Object.Equals(x, y);
}

public int GetHashCode(T obj)
{
throw new NotImplementedException();
}
}
通过看这段代码,有两处比较有意思的事情:
1.几个相等比较的接口:

IComparable<(Of <(T>)>) 接口定义 CompareTo 方法,该方法确定实现类型的实例的排序顺序。 IEquatable<(Of <(T>)>) 接口定义 Equals 方法,该方法确定实现类型的实例的相等性。

2.关于Enumerable对象的比较:

会顺序的比较两序列相同位置元素的值。

 

当被比较的对象没有实现以上的任何接口时,调用Object类的Equals静态方法进行相等性比较。

另外,在两个Enumerable对象比较过程中,在比较其中单个元素时,用的是

innerComparer.Equals(enumeratorX.Current, enumeratorY.Current))
这样,如果每个元素又是Enumerable对象的话,会继续进行序列比较。

转载于:https://www.cnblogs.com/bangbang/archive/2011/11/26/2262469.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值