web-dev-qa-db-fra.com

C # - Affirmer que deux objets sont égaux dans les tests unitaires

Soit en utilisant Nunit ou Microsoft.VisualStudio.TestTools.UnitTesting. En ce moment, mon affirmation échoue.

    [TestMethod]
    public void GivenEmptyBoardExpectEmptyBoard()
    {
        var test = new Board();

        var input = new Board()
            {
                Rows = new List<Row>()
                    {
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                    }
            };

        var expected = new Board()
        {
            Rows = new List<Row>()
                    {
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                        new Row(){Cells = new List<int>(){0,0,0,0}},
                    }
        };

        var lifeOrchestration = new LifeOrchestration();

        var actual = lifeOrchestration.Evolve(input);

        Assert.AreEqual(expected, actual);
    }
14

Vous avez deux instances Board différentes, votre appel à Assert.AreEqual échouera. Même si tout leur contenu semble être identique, vous comparez des références et non les valeurs sous-jacentes.

Vous devez spécifier ce qui rend égales deux instances Board.

Vous pouvez le faire dans votre test:

Assert.AreEqual(expected.Rows.Count, actual.Rows.Count);
Assert.AreEqual(expected.Rows[0].Cells[0], actual.Rows[0].Cells[0]);

// Lots more tests of equality...

Ou vous pouvez le faire dans vos cours: (remarque j'ai écrit ceci à la volée - vous voudrez ajuster ceci)

public class Board
{
    public List<Row> Rows = new List<Row>();

    public override bool Equals(object obj)
    {
        var board = obj as Board;

        if (board == null)
            return false;

        if (board.Rows.Count != Rows.Count)
            return false;

        return !board.Rows.Where((t, i) => !t.Equals(Rows[i])).Any();
    }

    public override int GetHashCode()
    {
        // determine what's appropriate to return here - a unique board id may be appropriate if available
    }
}

public class Row
{
    public List<int> Cells = new List<int>(); 

    public override bool Equals(object obj)
    {
        var row = obj as Row;

        if (row == null)
            return false;

        if (row.Cells.Count != Cells.Count)
            return false;

        if (row.Cells.Except(Cells).Any())
            return false;

        return true;
    }

    public override int GetHashCode()
    {
        // determine what's appropriate to return here - a unique row id may be appropriate if available
    }
}
15
Grant

J'avais l'habitude de remplacer getHasCode et égal à, mais je ne l'ai jamais aimé, car je ne veux pas changer mon code de production pour des raisons de tests unitaires ... C'est aussi un peu pénible.

Ensuite, je me suis tourné trop vers la réflexion pour comparer des objets moins invasifs ... mais ça demande beaucoup de travail (beaucoup de cas d'angle)

Au final j'utilise:

http://www.nuget.org/packages/DeepEqual/

Fonctionne très bien.

9
foobarcode

ExpectedObjects vous aiderait à comparer l'égalité par valeur de propriété. Elle supporte:

  1. objet simple: attendu.ToExpectedObject (). ShouldEqual (actual);
  2. collection: attendu.ToExpectedObject (). ShouldEqual (actual);
  3. objet composé: attendu.ToExpectedObject (). ShouldEqual (actual);
  4. comparaison partielle: conception des besoins attendue de l'objet avec un type anonyme, et utilisation de expect.ToExpectedObject (). ShouldMatch (actual)

J'adore ExpectedObjects car je n'ai besoin que d'appeler 2 API pour affirmer la comparaison de l'égalité d'objet:

  1. ShouldEqual ()
  2. ShouldMatch () pour une comparaison partielle
7
In91

Je souhaitais une solution ne nécessitant pas l'ajout d'une dépendance, travaillais avec des tests unitaires VS, comparait les valeurs de champ de deux objets et m'indiquait tous les champs inégaux. C'est ce que je suis venu avec. Notez qu'il pourrait également être étendu pour fonctionner avec les valeurs de propriété.

Dans mon cas, cela fonctionne bien pour comparer les résultats d'une logique d'analyse de fichiers afin de garantir que deux entrées techniquement "différentes" ont des champs avec les mêmes valeurs.

    public class AssertHelper
    {
        public static void HasEqualFieldValues<T>(T expected, T actual)
        {
            var failures = new List<string>();
            var fields = typeof(T).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
            foreach(var field in fields)
            {
                var v1 = field.GetValue(expected);
                var v2 = field.GetValue(actual);
                if (v1 == null && v2 == null) continue;
                if(!v1.Equals(v2)) failures.Add(string.Format("{0}: Expected:<{1}> Actual:<{2}>", field.Name, v1, v2));
            }
            if (failures.Any())
                Assert.Fail("AssertHelper.HasEqualFieldValues failed. " + Environment.NewLine+ string.Join(Environment.NewLine, failures));
        }
    }

    [TestClass]
    public class AssertHelperTests
    {
        [TestMethod]     
        [ExpectedException(typeof(AssertFailedException))]           
        public void ShouldFailForDifferentClasses()
        {            
            var actual = new NewPaymentEntry() { acct = "1" };
            var expected = new NewPaymentEntry() { acct = "2" };
            AssertHelper.HasEqualFieldValues(expected, actual);
        }
    }
6
Daniel

Les méthodes d'assertion s'appuient sur Equals et GetHashcode de l'objet. Vous pouvez implémenter cela, mais si cette égalité d'objet n'est pas nécessaire en dehors des tests unitaires, je considérerais plutôt comparer les types primitifs individuels sur l'objet. On dirait que les objets sont assez simples et qu’il n’est pas nécessaire de passer outre à des valeurs égales.

0
TGH