35

私は単体テストにかなり慣れていないので、今のところすべてうまくいっています。ここでは問題を単純化していますが、基本的には次のとおりです。

[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);
}

しかし、テストは失敗しています。テストに合格すべきではないでしょうか? 私は何が欠けていますか?

4

6 に答える 6

66

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

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

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

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

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

    public override bool Equals(object obj)
    {
        return this.ID == (obj as Example).ID;
    }
}
于 2013-11-08T14:59:24.870 に答える
14

このテストを機能させる非常に簡単な方法は、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);
}

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

于 2013-11-08T14:51:59.613 に答える
10

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

Assert.IsTrue(actual.SequenceEqual(expected));
于 2013-11-08T14:49:01.020 に答える
9

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

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

IEquatableインターフェイスを実装することで、ほとんどのことを行うことができます。このインターフェイスを実装するときは、一貫した結果を得るためにオーバーライドする必要があることに注意してください。Object.EqualsObject.GetHashCode

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

于 2013-11-08T15:00:48.653 に答える
4

Nunitのドキュメントから:

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

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


私が言ったように (そして他のほとんどの場合も)、おそらく Equals をオーバーライドする必要があります。これを行う方法についてのMSDNページは次のとおりです(Equals、==演算子、およびGetHashCodeをカバーしています)。

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

于 2013-11-08T14:45:37.907 に答える
2

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

[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();
}
于 2015-06-09T18:15:47.753 に答える