4

私は多くの指示を見てきました (なぜ Assert.AreEqual(T obj1, Tobj2) は同一のオブジェクトで失敗するのですかユニットテスト Assert.AreEqual が失敗しましたAssert.AreEqual は同じタイプで失敗しますEquals) /IEqualityComparerをチェックしたい場合は、クラスに実装します参照ではなくフィールド値に基づく等価性。

そうしようとして、私はそれを機能させることができず、問題を次のように絞り込みました。

私のクラスのサブジェクトをテストする必要があります。SubjectTestEqualでは、両方のインスタンスが等しいと予想されますが、結果は「Assert.AreEqual が失敗しました。また、コードをデバッグすると、EqualsGetHashCodeへの呼び出しが表示されません。

不可解な「Default プロパティは、型 T が System.IEquatable インターフェイスを実装しているかどうかをチェックし、実装している場合は、その実装を使用する EqualityComparer を返します。それ以外の場合は、提供された Object.Equals および Object.GetHashCode のオーバーライドを使用する EqualityComparer を返します。時間あたり。" EqualityComparer.Default プロパティのドキュメントでは、IEquatable (効果を確認するためにコードのコメントを解除) も試してみましたが、役に立ちませんでした。

public class Subject : IEqualityComparer<Subject>//, IEquatable<Subject>
{
    public int Id { get; set; }

    public Subject(int name) { Id = name; }

    public bool Equals(Subject x, Subject y)
    { return (x.Id == y.Id); }

    public int GetHashCode(Subject obj)
    { return Id; }

    //public bool Equals(Subject other)
    //{ return Equals(this, other); }
}

[TestClass]
public class SubjectTest
{
    [TestMethod]
    public void SubjectTestEqual()
    { Assert.AreEqual<Subject>(new Subject(1), new Subject(1)); }

    [TestMethod]
    public void SubjectTestSame()
    {
        Subject test = new Subject(1);
        Assert.AreEqual<Subject>(test, test);
    }
}

誰でもこれに光を当てることができますか?

4

4 に答える 4

5

自分のメソッドを呼び出すには、基本メソッドをオーバーライドする必要があります。

public override bool Equals(object obj)
{ ... }

public override int GetHashCode()
{ ... }

ただし、基本メソッドEqualsと同じ署名を適用する必要があります。GetHashcode

于 2013-03-06T15:49:26.450 に答える
1

あなたの答えをありがとう、彼らはこれについてさらに助けてくれましたが、どれも私を完全に助けてくれませんでした.

次のように、オブジェクトの Equals および GetHashCode メソッドをオーバーライドすると:

public override bool Equals(object obj)
{ return true; }

public override int GetHashCode()
{ return 0; }

メソッドが呼び出され、テストが成功します。ただし、もちろん、オブジェクト型のパラメーターに対してこれらのメソッドを実装したくありません。クラスがインスタンスをオブジェクトの任意のインスタンスと比較することを提案するのはなぜですか?

そこで、このメソッドを static に変更public **static** bool Equals(Subject x, Subject y)し、新しいテスト メソッドを導入しました (簡潔にするために、すべてのテストを 1 つのメソッドで行います)。

    [TestMethod]
    public void SubjectTestWithSubjectEquals()
    {
        Assert.IsTrue(Subject.Equals(new Subject(1), new Subject(1)));
        Assert.IsTrue(new Subject(1).Equals(new Subject(1)));
        Assert.IsFalse(Subject.Equals(new Subject(1), new Subject(2)));
        Assert.IsFalse(new Subject(1).Equals(new Subject(2)));
    }

これらのテストは成功します。ただし、これが良い方法であるかどうかはわかりません。一つにはAssert.IsTrue((new Subject(1)) == (new Subject(1)));、成功するために、私は以下を実装する必要がありました:

public static bool operator ==(Subject x, Subject y)
    { return Equals(x, y); }

また、次のことも必要です。

public static bool operator !=(Subject x, Subject y)
    { return !Equals(x, y); }

また、さらに一歩進んで、タイプ Subject のリストを比較できるようにしたいので、次のテストを試しました。

[TestMethod]
public void SubjectTestWithCollections()
{
    var list1 = new List<Subject>() { new Subject(1), new Subject(2) };
    var list2 = new List<Subject>() { new Subject(1), new Subject(2) };
    CollectionAssert.AreEqual(list1, list2);
}

どうやら各項目は Subject.Equals ではなく Assert.AreEqual を使用して比較されるため、これは失敗します。CollectionAssert.AreEquivalent の問題を見てきました。これは、主に Microsoft.VisualStudio.TestTools.UnitTesting の実装方法が原因なのか、それとも一般的に Equals で大騒ぎするべきではないのか疑問に思います。

于 2013-03-07T13:07:38.267 に答える
0

TestClassがのコントラクトに違反していObject.Equalsます。Assert.AreEqualかなり合理的に、その契約に依存しています。

ドキュメントの状態(要件のリスト内):

x.Equals(null参照(Visual BasicではNothing))はfalseを返します。

于 2013-03-06T15:51:11.533 に答える
0

Assert.AreEqualEquals渡された最初のパラメーターのメソッドを排他的に使用します。これでIEqualityComparer実装に関する知識が得られたので、使用されません。

通常、クラスがオブジェクトの等価性を比較する必要がある場合、オブジェクト自体IEqualityComparerのメソッドの代わりにクラスが比較を行うために使用できるan のオプションのパラメーターがありますが、そのようなパラメーターは受け入れません。これは、使用するには、から継承されたメソッドをオーバーライドする必要があることを意味します。つまり、次のとおりです。EqualsAssert.AreEqualAssert.AreEqualEqualsobject

public override bool Equals(object obj){}

IEqualityComparer 型が独自の型を実装することはほとんど意味がありません。の考え方は、「自分自身」ではなく、他のタイプIEqualityComparerを同等に比較できるようにすることです。

于 2013-03-06T15:54:37.547 に答える