4
public class Foo
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Z { get; set; }

    public override int GetHashCode()
    {
        var hash = 17;
        hash *= 23 + x.GetHashCode();
        hash *= 23 + y.GetHashCode();
        hash *= 23 + z.GetHashCode();
    }
}

GetHashCode の単体テストに進むと、元のコンポーネントを計算するか、関数を繰り返すか、事前に定義された値を使用するかで迷っています。

[TestMethod]
public void Test1
{
    var x = 1; y = 2; z = 3;
    var foo = new Foo() { X = x, Y = y, Z = z };

    var hash = 17;
    hash *= 23 + x.GetHashCode();
    hash *= 23 + y.GetHashCode();
    hash *= 23 + z.GetHashCode();

    var expected = hash;
    var actual = foo.GetHashCode();

    Assert.AreEqual(expected, actual);
}

[TestMethod]
public void Test2
{
    var x = 1; y = 2; z = 3;
    var foo = new Foo() { X = x, Y = y, Z = z };

    var expected = ? //Some predetermined value (calculated by hand?)
    var actual = foo.GetHashCode();

    Assert.AreEqual(expected, actual);
}

それとも何か他の方法がありますか?

4

2 に答える 2

5

ユニットテストは、ロジックをテストするためのものです。GetHashCode計算自体は論理ですか?意見は異なるかもしれませんが、実際にはそうではありません。

ここでの関連する論理は、等しい2つのオブジェクトが同じハッシュコードを持っている、つまり互換性があるというEqualsことです。または、ドキュメントHashCodeからの引用:

  • 2つのオブジェクトが等しいと比較される場合、各オブジェクトのGetHashCodeメソッドは同じ値を返す必要があります。ただし、2つのオブジェクトが同等であると比較されない場合、2つのオブジェクトのGetHashCodeメソッドは異なる値を返す必要はありません。

  • オブジェクトのGetHashCodeメソッドは、オブジェクトのEqualsメソッドの戻り値を決定するオブジェクトの状態に変更がない限り、一貫して同じハッシュコードを返す必要があります。これはアプリケーションの現在の実行にのみ当てはまり、アプリケーションを再度実行すると別のハッシュコードが返される可能性があることに注意してください。

GetHashCodeしたがって、の内部実装が所定の手順に一致するのではなく、これらの条件が満たされていることを保証する単体テストを作成します。

両方のサンプルテストは非常に脆弱であり、完全に有効なGetHashCode実装では失敗します。単体テストの主な目的の1つは、恐れることなくリファクタリングを可能にすることであることを思い出してください。GetHashCodeただし、ユニットテストを中断せずにリファクタリングすることはできません。

于 2011-07-13T18:54:27.627 に答える
1

テスト対象の値を選択した理由を説明するために、多くのコメントを付けて、結果を事前に計算された値と比較します。

純粋な計算の場合、関数がそれを使用するコードの必要/期待される条件を確実に維持するように、単体テストを作成する傾向があります。

条件の例:

  • 生成されるハッシュ値に制約はありますか? 最小値、最大値、奇数、偶数など
  • 正数と負数を適切にハッシュしていますか?
  • 適切な条件下で独自の価値を生み出しているか?
于 2011-07-13T19:02:58.960 に答える