C#:你如何对GetHashCode进行单元测试?

时间:2009-11-08 15:34:11

标签: c# unit-testing tdd gethashcode

测试Equals方法非常简单(据我所知)。但是你究竟如何测试GetHashCode方法?

7 个答案:

答案 0 :(得分:35)

测试两个相同的相同对象具有相同的哈希码(对于各种值)。检查不相等的对象是否给出不同的哈希码,一次改变一个方面/属性。虽然哈希码不会 不同,但你真的不幸选择发生的属性的不同值来提供相同的哈希码,除非你已经有一个错误。

答案 1 :(得分:9)

Gallio/MbUnit v3.2附带方便的合同验证程序,可以测试GetHashCode()IEquatable<T>的实施情况。更具体地说,您可能会对EqualityContractHashCodeAcceptanceContract感兴趣。有关详细信息,请参阅hereherethere

public class Spot
{
  private readonly int x;
  private readonly int y;

  public Spot(int x, int y)
  {
    this.x = x;
    this.y = y;
  }

  public override int GetHashCode()
  {
    int h = -2128831035;
    h = (h * 16777619) ^ x;
    h = (h * 16777619) ^ y;
    return h;
  }
}

然后你声明你的合同验证者:

[TestFixture]
public class SpotTest
{
  [VerifyContract]
  public readonly IContract HashCodeAcceptanceTests = new HashCodeAcceptanceContract<Spot>()
  {
    CollisionProbabilityLimit = CollisionProbability.VeryLow,
    UniformDistributionQuality = UniformDistributionQuality.Excellent,
    DistinctInstances = DataGenerators.Join(Enumerable.Range(0, 1000), Enumerable.Range(0, 1000)).Select(o => new Spot(o.First, o.Second))
  };
}

答案 2 :(得分:5)

它与Equals()非常相似。您需要确保两个“相同”的对象至少具有相同的哈希码。这意味着如果.Equals()返回true,则哈希码也应该相同。至于正确的哈希码值是什么,这取决于你如何散列。

答案 3 :(得分:3)

从个人经验来看。除了相同对象提供相同哈希码之类的显而易见的事情之外,您还需要创建足够大的唯一对象数组并在其中计算唯一的哈希码。如果唯一的哈希码比总体对象数少50%,那么你就麻烦了,因为你的哈希函数不好。

        List<int> hashList = new List<int>(testObjectList.Count);
        for (int i = 0; i < testObjectList.Count; i++)
        {
            hashList.Add(testObjectList[i]);
        }

        hashList.Sort();
        int differentValues = 0;
        int curValue = hashList[0];
        for (int i = 1; i < hashList.Count; i++)
        {
            if (hashList[i] != curValue)
            {
                differentValues++;
                curValue = hashList[i];
            }
        }

        Assert.Greater(differentValues, hashList.Count/2);

答案 4 :(得分:0)

我会预先提供已知/预期的哈希并比较GetHashCode的结果。

答案 5 :(得分:0)

使用相同的值创建单独的实例,并检查实例的GetHashCode是否返回相同的值,并且对同一实例的重复调用返回相同的值。

这是哈希码工作的唯一要求。为了更好地工作,哈希码当然应该具有良好的分布,但测试需要大量的测试...

答案 6 :(得分:0)

除了检查对象相等性意味着哈希码的相等性,并且正如Yann Trevin所建议的那样哈希的分布相当平坦(如果性能是一个问题),你可能还想考虑如果你改变一个属性会发生什么对象。

假设您的对象在字典/散列集中发生变化。你想要Contains(对象)仍然是真的吗?如果是这样,那么你的GetHashCode最好不要依赖于已更改的可变属性。