web-dev-qa-db-ja.com

2つのリストを比較するNUnit

わかりました。私はユニットテストにかなり慣れていないので、今まですべてが順調に進んでいます。ここでは問題を単純化していますが、基本的には次のようになっています。

[Test]
public void ListTest()
{
    var expected = new List<MyClass>();
    expected.Add(new MyOtherClass());
    var actual = new List<MyClass>();
    actual.Add(new MyOtherClass());
    Assert.AreEqual(expected,actual);
    //CollectionAssert.AreEqual(expected,actual);
}

しかし、テストは失敗しています。テストに合格するべきではありませんか?何が欠けていますか?

22
SOfanatic

リクエストに応じてコメントを回答に変換します。

AreEqualは参照比較を使用しているため、これは失敗します。これを機能させるには、値の比較(独自のカスタム比較)が必要です。

IEquatable インターフェースを実装することで、ほとんどのことを実行できます。このインターフェイスを実装するときは、次の点に注意してくださいmust override Object.EqualsおよびObject.GetHashCodeも一貫した結果を得るために。

.Netフレームワークは、IEquatableを実装せずにこれを行うことをサポートします IEqualityComparer がトリックを実行しますが、nunitはこれをオーバーロードとして受け取るメソッドを持つ必要があります。 「nunit」については確かではありません。

7

2つのリストを比較する場合は、 コレクション制約 を使用したテストを使用する必要があります。

Assert.That(actual, Is.EquivalentTo(expected));

また、クラスでは、Equalsメソッドをオーバーライドする必要があります。そうしないと、glengが述べたように、リスト内の項目は参照に基づいて比較されます。

簡単なオーバーライドの例:

public class Example
{
    public int ID { get; set; }

    public override bool Equals(object obj)
    {
        return this.ID == (obj as Example).ID;
    }
}
42
matth

このテストを機能させる非常に簡単な方法は、MyOtherClassインスタンスを1回だけ作成することです。このようにして、2つのリストのアイテムを比較すると、それらは「等しい」になります(同じオブジェクトを参照しているため)。これを行うと、CollectionAssertは問題なく動作します。

[Test]
public void ListTest()
{
    var thing = new MyOtherClass();

    var expected = new List<MyClass>();
    expected.Add(thing);

    var actual = new List<MyClass>();
    actual.Add(thing);

    CollectionAssert.AreEqual(expected,actual);
}

ただし、これを行わない場合は、MyOtherClassIEquatable<MyOtherClass>を実装するか、Equalsをオーバーライドして、そのクラスの2つのインスタンスを「同じ」にするものを定義する必要があります。

10
Jeff B

達成しようとしていることについて、もう少し具体的に説明してください。シーケンス全体を比較することを明示的に伝えると、問題が解決します。個人的には、AreEqualが言う意味を判断するためにNUnitのファンシー機能に依存することはありません。例えば。

Assert.IsTrue(actual.SequenceEqual(expected));
5
Klark

Nunitから ドキュメント

バージョン2.2以降では、1次元配列を比較するための特別な準備も行われています。 2つの配列が同じ長さで、対応する各要素が等しい場合、Assert.AreEqualは等しいと見なします。注:多次元配列、ネストされた配列(配列の配列)、およびArrayListなどの他のコレクション型は現在サポートされていません。

オブジェクトのリストがあるので、2つのintを比較するのと同じではありません。あなたがすべきことはおそらくリスト内のすべてのオブジェクトを比較することです...(リストを配列に変換してみてください...実際にはうまくいくかもしれません:))


私が言ったように(そして他のほとんどの人も)、おそらくEqualsをオーバーライドする必要があるでしょう。これがその方法についての [〜#〜] msdn [〜#〜] ページです(Covers Equals、==演算子、およびGetHashCode)。

詳細と同様:[compare-equality-between-two-objects-in-nunit]
NUnit内の2つのオブジェクト間の同等性を比較

2
Noctis

クラスを変更できない場合は、次の例が役立ちます。

[Test]
public void Arrays_Should_Be_Equal()
{
    MyClass[] array1 = GetTestArrayOfSize(10);
    MyClass[] array2 = GetTestArrayOfSize(10);

    // DOESN'T PASS
    // Assert.That(array1, Is.EquivalentTo(array2));

    Func<MyClass, object> selector = i => new { i.Property1, i.Property2 };
    Assert.That(array1.Select(selector), Is.EquivalentTo(array2.Select(selector)));
}

private MyClass[] GetTestArrayOfSize(int count)
{
    return Enumerable.Range(1, count)
        .Select(i => new MyClass { Property1 = "Property1" + i, Property2 = "Property2" + i }).ToArray();
}
1