XUnitフレームワークを使用してC#コードをテストしています。
オブジェクトの比較を行うこのフレームワークで利用可能なassertメソッドはありますか?私の目的は、オブジェクトのパブリックメンバー変数とプライベートメンバー変数のそれぞれが等しいかどうかをチェックすることです。
私はそれらの代替案を試しましたが、ほとんどうまくいきません:
1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally
これを行うには、カスタム比較子が必要です。オブジェクトを比較する場合、それ以外の場合は、メモリ内の同じオブジェクトを参照しているかどうかに基づいてチェックされます。この動作をオーバーライドするには、Equals
およびGetHashCode
メソッドをオーバーライドする必要があります。そうすると、次のようになります。
Assert.True(obj1.Equals(obj2));
これは、MSDNページのABTオーバーロードEqualsメソッドです: http://msdn.Microsoft.com/en-us/library/ms173147(v = vs.80).aspx
また、質問に対するコメントを適合させます: IEquatableとObject.Equals()をオーバーライドするだけの違いは何ですか?
同様の問題がありましたが、幸いにも私はすでに使用しています
using Newtonsoft.Json;
だから私はそれをjsonオブジェクトにシリアル化し、文字列として比較する必要がありました。
var obj1Str = JsonConvert.SerializeObject(obj1);
var obj2Str = JsonConvert.SerializeObject(obj2);
Assert.Equal(obj1Str, obj2Str );
これは古い質問であることはわかっていますが、偶然見つけたので、利用可能な新しいソリューション(少なくとも.net Core 2.0ソリューションのxunit 2.3.1)を検討する必要があると考えました。
いつ導入されたかはわかりませんが、_.Equal
_のインスタンスを3番目のパラメーターとして受け入れるオーバーロードされた形式の_IEqualityComparer<T>
_が存在します。ユニットテストでコードを汚染することなく、カスタムコンパレータを作成できます。
次のコードは、このようにして呼び出すことができます:Assert.Equal(expectedParameters, parameters, new CustomComparer<ParameterValue>());
XUnitは、障害が発生するとすぐにテストの処理を停止するように見えます。そのため、コンパレーター内から新しいEqualException
をスローすることは、XUnitがそのまま機能する方法と一致しているようです。
_public class CustomComparer<T> : IEqualityComparer<T>
{
public bool Equals(T expected, T actual)
{
var props = typeof(T).GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
foreach (var prop in props)
{
var expectedValue = prop.GetValue(expected, null);
var actualValue = prop.GetValue(actual, null);
if (!expectedValue.Equals(actualValue))
{
throw new EqualException($"A value of \"{expectedValue}\" for property \"{prop.Name}\"",
$"A value of \"{actualValue}\" for property \"{prop.Name}\"");
}
}
return true;
}
public int GetHashCode(T parameterValue)
{
return Tuple.Create(parameterValue).GetHashCode();
}
}
_
編集:実際の値と期待される値を_!=
_と比較しても、特定のタイプでは効果がないことがわかりました(参照タイプと値タイプの違いに関する詳細な説明があるはずです) 、しかしそれは今日のためではない)。 _.Equals
_メソッドを使用して2つの値を比較するようにコードを更新しましたが、これははるかにうまく機能するようです
これを行うNuGetパッケージがあります。個人的に使用する2つの例を次に示します。
object1.ShouldDeepEqual(object2);
[Fact]
public void RetrievingACustomer_ShouldReturnTheExpectedCustomer()
{
// Arrange
var expectedCustomer = new Customer
{
FirstName = "Silence",
LastName = "Dogood",
Address = new Address
{
AddressLineOne = "The New-England Courant",
AddressLineTwo = "3 Queen Street",
City = "Boston",
State = "MA",
PostalCode = "02114"
}
}.ToExpectedObject();
// Act
var actualCustomer = new CustomerService().GetCustomerByName("Silence", "Dogood");
// Assert
expectedCustomer.ShouldEqual(actualCustomer);
}
FluentAssertionsライブラリには、かなり強力な比較ロジックが含まれています。
myObject.ShouldBeEquivalentTo(new { SomeProperty = "abc", SomeOtherProperty = 23 });
これを使用して、「myObject」の一部をアサートすることもできます。ただし、プライベートフィールドでは役に立たない場合があります。