21

2 つのリストの要素には、期待どおりの値が含まれていると断言したいと思います。たとえば、次のようなものです。

var foundCollection = fooManager.LoadFoo();
var expectedCollection = new List<Foo>() 
{
    new Foo() { Bar = "a", Bar2 = "b" },
    new Foo() { Bar = "c", Bar2 = "d" }
};

//assert: I use AreEquivalent since the order does not matter
CollectionAssert.AreEquivalent(expectedCollection, foundCollection);

ただし、上記のコードは機能しません (同じ値を持つ異なるオブジェクトに対して .Equals() が true を返さないためだと思います)。私のテストでは、オブジェクトが等しいかどうかではなく、パブリック プロパティの値のみを気にします。自分の主張をするにはどうすればよいですか?

4

10 に答える 10

22

作り直された答え

オブジェクトの等価性をチェックCollectionAssert.AreEqual(IEnumerable, IEnumerable, IComparer)する実装を使用して、2 つのコレクションに同じオブジェクトが同じ順序で含まれていることをアサートするオーバーロードがあります。IComparer

上記のシナリオでは、順序は重要ではありません。ただし、2 つのコレクションに複数の同等のオブジェクトが存在する状況にも十分に対応するには、最初に各コレクション内のオブジェクトを並べ替え、1 つずつ比較して同等のオブジェクトの数も同じであることを確認する必要があります。 2つのコレクションで。

Enumerable.OrderByIComparer<T>引数を取るオーバーロードを提供します。2 つのコレクションが同じ順序で並べ替えられるようにするには、識別プロパティの型が を実装する必要がありますIComparableIComparerとの両方のIComparer<Foo>インターフェイスを実装する比較クラスの例を次に示します。ここでは、Bar順序付け時に が優先されると想定されています。

public class FooComparer : IComparer, IComparer<Foo>
{
    public int Compare(object x, object y)
    {
        var lhs = x as Foo;
        var rhs = y as Foo;
        if (lhs == null || rhs == null) throw new InvalidOperationException();
        return Compare(lhs, rhs);
    }

    public int Compare(Foo x, Foo y)
    {
        int temp;
        return (temp = x.Bar.CompareTo(y.Bar)) != 0 ? temp : x.Bar2.CompareTo(y.Bar2);
    }
}

2 つのコレクション内のオブジェクトが同じであり、同じ数である (ただし、最初から同じ順序である必要はありません) ことを主張するには、次の行でうまくいきます。

var comparer = new FooComparer();
CollectionAssert.AreEqual(
    expectedCollection.OrderBy(foo => foo, comparer), 
    foundCollection.OrderBy(foo => foo, comparer), comparer);    
于 2012-08-29T08:19:20.820 に答える
7

いいえ、NUnit には現在の状態ではそのようなメカニズムはありません。独自のアサーション ロジックを作成する必要があります。別の方法として、または以下を利用しHas.All.Matchesます。

Assert.That(found, Has.All.Matches<Foo>(f => IsInExpected(f, expected)));

private bool IsInExpected(Foo item, IEnumerable<Foo> expected)
{
    var matchedItem = expected.FirstOrDefault(f => 
        f.Bar1 == item.Bar1 &&
        f.Bar2 == item.Bar2 &&
        f.Bar3 == item.Bar3
    );

    return matchedItem != null;
}

もちろん、これは、関連するすべてのプロパティを事前に知っていることを前提としており (そうでない場合は、IsInExpectedリフレクションに頼る必要があります)、要素の順序は関係ありません。

(そして、あなたの仮定は正しかったです.NUnitのコレクションアサートは、ほとんどの場合、ユーザー定義のものはオブジェクトのタイプにデフォルトの比較子を使用しますReferenceEquals

于 2012-08-29T07:47:15.037 に答える
6

Has.All.Matches() を使用すると、見つかったコレクションと予想されるコレクションを比較するのに非常にうまく機能します。ただし、Has.All.Matches() で使用される述語を別の関数として定義する必要はありません。比較的単純な比較のために、このように述語をラムダ式の一部として含めることができます。

Assert.That(found, Has.All.Matches<Foo>(f => 
    expected.Any(e =>
        f.Bar1 == e.Bar1 &&
        f.Bar2 == e.Bar2 &&
        f.Bar3 == e.Bar3)));

ここで、このアサーションは、見つかったコレクションのすべてのエントリが期待されるコレクションにも存在することを保証しますが、その逆、つまり、期待されるコレクションのすべてのエントリが見つかったコレクションに含まれていることを証明しません。したがって、 foundexpectedの内容が意味的に同等であることを知ることが重要な場合(つまり、意味的に同等の同じエントリが含まれている場合)、追加のアサーションを追加する必要があります。

最も簡単な選択は、以下を追加することです。

Assert.AreEqual(found.Count(), expected.Count());

より大きなハンマーを好む人は、代わりに次のアサーションを使用できます。

Assert.That(expected, Has.All.Matches<Foo>(e => 
    found.Any(f =>
        e.Bar1 == f.Bar1 &&
        e.Bar2 == f.Bar2 &&
        e.Bar3 == f.Bar3)));

上記の最初のアサーションを 2 番目 (推奨) または 3 番目のアサーションと組み合わせて使用​​することにより、2 つのコレクションが意味的に同じであることを証明しました。

于 2014-04-22T21:30:50.300 に答える
3

このようなことを試しましたか?

Assert.That(expectedCollection, Is.EquivalentTo(foundCollection))
于 2012-08-29T06:40:41.987 に答える
2

同様の問題がありました。「コメント投稿者」やその他の投稿者を含む投稿者のリスト... すべてのコメントを取得し、そこから作成者を導き出したいのですが、私はユニークな作成者にしか興味がありません。誰かが 50 件のコメントを作成した場合、その名前を 1 回だけ表示したいと考えています。そこで、コメント投稿者が GetContributors() の結果に含まれていることを確認するテストを作成します。

私は間違っているかもしれませんが、あなたのその後 (この投稿を見つけたときに私が求めていたもの) は、あるコレクションにある各アイテムが別のコレクションにあると断言することです。

私はこれを次のように解決しました:

Assert.IsTrue(commenters.All(c => actual.Count(p => p.Id == c.Id) == 1));

結果のリストに予想以外のアイテムが含まれないようにしたい場合は、リストの長さを比較することもできます..

Assert.IsTrue(commenters.length == actual.Count());

これが役に立てば幸いです。そうであれば、私の回答を評価していただければ幸いです。

于 2014-10-15T11:47:54.950 に答える
1

複合型に対して等価演算を実行するには、IComaprable を実装する必要があります。

http://support.microsoft.com/kb/320727

あるいは、再帰反射を使用することもできますが、これはあまり望ましくありません。

于 2012-08-29T06:10:36.420 に答える
1

1 つのオプションは、項目を比較するためのカスタム制約を作成することです。この件に関する素晴らしい記事は次のとおりです

于 2012-08-29T07:53:36.347 に答える