J'utilise le framework XUnit pour tester mon code C #.
Existe-t-il une méthode d'assertion disponible dans ce cadre qui effectue la comparaison d'objets? Mon intention est de vérifier l'égalité de chacune des variables membres publiques et privées de l'objet.
J'ai essayé ces alternatives mais ça marche rarement:
1) bool IsEqual = (Obj1 == Obj2)
2) Assert.Same(Obj1, Obj2) which I couldnt understand what happens internally
Vous devez disposer d'un comparateur personnalisé pour y parvenir, lorsque vous comparez des objets, sinon ils sont vérifiés selon qu'ils se réfèrent au même objet en mémoire. Pour remplacer ce comportement, vous devez remplacer la méthode Equals
et GetHashCode
et vous pourriez alors faire:
Assert.True(obj1.Equals(obj2));
Voici une page MSDN abt surchargeant la méthode Equals: http://msdn.Microsoft.com/en-us/library/ms173147 (v = vs.80) .aspx
Convient également le commentaire sur la question: Quelle est la différence entre IEquatable et simplement remplacer Object.Equals ()?
J'ai eu un problème similaire, mais heureusement, j'utilise déjà
using Newtonsoft.Json;
J'ai donc juste eu à le sérialiser en objet json puis à le comparer sous forme de chaîne.
var obj1Str = JsonConvert.SerializeObject(obj1);
var obj2Str = JsonConvert.SerializeObject(obj2);
Assert.Equal(obj1Str, obj2Str );
Je sais que c'est une vieille question, mais depuis que je suis tombé dessus, j'ai pensé que je peserais avec une nouvelle solution qui est disponible (au moins dans xunit 2.3.1 dans une solution .net Core 2.0).
Je ne sais pas quand il a été introduit, mais il existe maintenant une forme surchargée de .Equal
Qui accepte une instance de IEqualityComparer<T>
Comme troisième paramètre. Vous pouvez créer un comparateur personnalisé dans votre test unitaire sans polluer votre code avec.
Le code suivant peut être appelé comme ceci: Assert.Equal(expectedParameters, parameters, new CustomComparer<ParameterValue>());
XUnit semble nativement arrêter le traitement d'un test dès qu'un échec est rencontré, donc lancer un nouveau EqualException
depuis notre comparateur semble être en ligne avec la façon dont XUnit fonctionne hors de la boîte.
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();
}
}
Edit: j'ai trouvé que la comparaison des valeurs réelles et attendues avec !=
N'était pas efficace pour certains types (je suis sûr qu'il y a une meilleure explication impliquant la différence entre les types de référence et les types de valeur, mais ce n'est pas pour aujourd'hui). J'ai mis à jour le code pour utiliser la méthode .Equals
pour comparer les deux valeurs et cela semble fonctionner beaucoup mieux.
Il existe des packages NuGet qui le font pour vous. Voici deux exemples que j'utilise personnellement.
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);
}
La bibliothèque FluentAssertions a une logique de comparaison assez puissante à l'intérieur.
myObject.ShouldBeEquivalentTo(new { SomeProperty = "abc", SomeOtherProperty = 23 });
Vous pouvez même l'utiliser pour affirmer une partie de "myObject". Cependant, cela peut ne pas vous aider avec les champs privés.