テスティングフレームワークとしてxUnit.netを使ったところ、独自クラスに対してAssert.Equalする時に少し悩んだのでメモを残しておきます。
環境
- Visual Studio 2013 Community
- xUnit.net 2.0.0
悩んだところ
独自クラスをプロパティとして持つクラスを用意します。
public class Target { public Pair KeyValuePair { get; private set; } public void SetKeyValue(string key, string value) { KeyValuePair = new Pair() { Key = key, Value = value }; } } public class Pair { public string Key { get; set; } public string Value { get; set; } }
このクラスのSetKeyValue
メソッドの動作をテストするため、以下の様なテストコードを書きました。
const string HogeKey = "hoge"; const string FugaValue = "fuga"; [Fact] public void FailTest() { var expected = new Pair() { Key = HogeKey, Value = FugaValue }; var actual = new Target(); actual.SetKeyValue(HogeKey, FugaValue); Assert.Equal(expected, actual.KeyValuePair); }
テストを実行すると失敗しました。各プロパティの値は一致していますが、参照が異なるせいか別モノと認識されているようです。
対応
Assert.Equal
メソッドを定義しているEqualityAsserts.cs
のコードを読むと、Assert.Equal
にはオーバーロードがいくつかあり、その内の1つにIEqualityComparer<T>
を引数に持つものがありました。
そのため、まずはIEqualityComparer
を実装したクラスを作りました。
public class PairComparer : IEqualityComparer<Pair> { public bool Equals(Pair x, Pair y) { // 2つのオブジェクトを等しいとみなす条件 return x.Key.Equals(y.Key, StringComparison.Ordinal) && x.Value.Equals(y.Value, StringComparison.Ordinal); } public int GetHashCode(Pair pair) { // Equals対象のプロパティのHashのXORをHashCodeとして返す return pair.Key.GetHashCode() ^ pair.Value.GetHashCode(); } }
次に、Equalメソッドの第三引数に上記のクラスを渡すよう修正したところ、expectedとactualが同じものと認識され、テストが通りました。
Assert.Equal(expected, actual.KeyValuePair, new PairComparer());
ソースコード
GitHubに上げておきました。
thinkAmi-sandbox/xUnit-TwoObjectsEquality-sample
参考
IEqualityComparerを使う方法
文字列の比較