web-dev-qa-db-ja.com

CollectionAssertはジェネリックで使用しますか?

CollectionAssertはジェネリックでは使用できないようです。これは非常に苛立たしいことです。テストしたいコードはジェネリックを使用しています。どうしようかな? 2つの間で変換する定型文を書きますか?コレクションの同等性を手動で確認しますか?

これは失敗します:

ICollection<IDictionary<string, string>> expected = // ...

IEnumerable<IDictionary<string, string>> actual = // ...

// error 1 and 2 here
CollectionAssert.AreEqual(expected.GetEnumerator().ToList(), actual.ToList());

// error 3 here
Assert.IsTrue(expected.GetEnumerator().SequenceEquals(actual));

コンパイラエラー:

エラー1:

'System.Collections.Generic.IEnumerator>'には 'ToList'の定義が含まれておらず、タイプ 'System.Collections.Generic.IEnumerator>'の最初の引数を受け入れる拡張メソッド 'ToList'が見つかりませんでした

エラー2

'System.Collections.Generic.IEnumerator>'には 'ToList'の定義が含まれておらず、タイプ 'System.Collections.Generic.IEnumerator>'の最初の引数を受け入れる拡張メソッド 'ToList'が見つかりませんでした

エラー3

'System.Collections.Generic.IEnumerator>'には 'SequenceEquals'の定義が含まれておらず、タイプ 'System.Collections.Generic.IEnumerator>'の最初の引数を受け入れる拡張メソッド 'SequenceEquals'が見つかりませんでした

私は何が間違っているのですか?拡張機能を正しく使用していませんか?

更新:わかりました、これは少し良く見えますが、それでも機能しません:

IEnumerable<IDictionary<string, string>> expected = // ...

IEnumerable<IDictionary<string, string>> actual = // ...

CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); // fails
CollectionAssert.IsSubsetOf(expected.ToList(), actual.ToList()); // fails

リストを比較したくありません。私はセットメンバーシップの平等だけを気にします。メンバーの順序は重要ではありません。どうすればこれを回避できますか?

35
Nick Heiner

あなたcanジェネリックコレクションでCollectionAssertを使用します。秘訣は、CollectionAssertメソッドがICollectionで動作することを理解することです。また、ICollectionを実装する汎用コレクションインターフェイスはほとんどありませんが、_List<T>_は実装しています。

したがって、ToList拡張メソッドを使用することでこの制限を回避できます:

_IEnumerable<Foo> expected = //...
IEnumerable<Foo> actual = //...
CollectionAssert.AreEqual(expected.ToList(), actual.ToList());
_

そうは言っても、私はまだCollectionAssertが他の多くの方法で壊れていると考えているので、次のようにLINQ拡張メソッドでAssert.IsTrue(bool)を使用する傾向があります。

_Assert.IsTrue(expected.SequenceEqual(actual));
_

FWIW、私は現在、これらの拡張メソッドを使用して他の比較を実行しています。

_public static class EnumerableExtension
{
    public static bool IsEquivalentTo(this IEnumerable first, IEnumerable second)
    {
        var secondList = second.Cast<object>().ToList();
        foreach (var item in first)
        {
            var index = secondList.FindIndex(item.Equals);
            if (index < 0)
            {
                return false;
            }
            secondList.RemoveAt(index);
        }
        return secondList.Count == 0;
    }

    public static bool IsSubsetOf(this IEnumerable first, IEnumerable second)
    {
        var secondList = second.Cast<object>().ToList();
        foreach (var item in first)
        {
            var index = secondList.FindIndex(item.Equals);
            if (index < 0)
            {
                return false;
            }
            secondList.RemoveAt(index);
        }
        return true;
    }
}
_
36
Mark Seemann

セットを使用している場合は、このイディオムを使用してください

HashSet<string> set1  = new HashSet<string>(){"A","B"};
HashSet<string> set2  = new HashSet<string>(){"B","A"};

Assert.IsTrue(set1.SetEquals(set2));
5
Sudipta

独自の汎用バージョンを簡単に作成し、それをすべてのテストで使用される基本クラスまたはユーティリティクラスに移動できます。 AllやAnyなどのLINQ演算子に基づいてください。

1
John Saunders