web-dev-qa-db-ja.com

オブジェクトの等価性をチェックするためのXUnitアサーション

XUnitフレームワークを使用してC#コードをテストしています。

オブジェクトの比較を行うこのフレームワークで利用可能なassertメソッドはありますか?私の目的は、オブジェクトのパブリックメンバー変数とプライベートメンバー変数のそれぞれが等しいかどうかをチェックすることです。

私はそれらの代替案を試しましたが、ほとんどうまくいきません:

1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally
27
inquisitive

これを行うには、カスタム比較子が必要です。オブジェクトを比較する場合、それ以外の場合は、メモリ内の同じオブジェクトを参照しているかどうかに基づいてチェックされます。この動作をオーバーライドするには、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()をオーバーライドするだけの違いは何ですか?

14
Baz1nga

同様の問題がありましたが、幸いにも私はすでに使用しています

using Newtonsoft.Json;

だから私はそれをjsonオブジェクトにシリアル化し、文字列として比較する必要がありました。

var obj1Str = JsonConvert.SerializeObject(obj1);
var obj2Str = JsonConvert.SerializeObject(obj2);
Assert.Equal(obj1Str, obj2Str );
35
The Integrator

これは古い質問であることはわかっていますが、偶然見つけたので、利用可能な新しいソリューション(少なくとも.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つの値を比較するようにコードを更新しましたが、これははるかにうまく機能するようです

6
Engineer_Andrew

これを行うNuGetパッケージがあります。個人的に使用する2つの例を次に示します。

  1. DeepEqual

    object1.ShouldDeepEqual(object2);
    
  2. ExpectedObjects

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

FluentAssertionsライブラリには、かなり強力な比較ロジックが含まれています。

myObject.ShouldBeEquivalentTo(new { SomeProperty = "abc", SomeOtherProperty = 23 });

これを使用して、「myObject」の一部をアサートすることもできます。ただし、プライベートフィールドでは役に立たない場合があります。

0
Adrian Petrescu