C # – Asserire due oggetti sono uguali nei test unitari

Utilizzando Nunit o Microsoft.VisualStudio.TestTools.UnitTest. In questo momento la mia affermazione fallisce.

[TestMethod] public void GivenEmptyBoardExpectEmptyBoard() { var test = new Board(); var input = new Board() { Rows = new List() { new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, } }; var expected = new Board() { Rows = new List() { new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, new Row(){Cells = new List(){0,0,0,0}}, } }; var lifeOrchestration = new LifeOrchestration(); var actual = lifeOrchestration.Evolve(input); Assert.AreEqual(expected, actual); } 

Hai due diverse istanze di Board , quindi la tua chiamata ad Assert.AreEqual fallirà. Anche se il loro intero contenuto sembra essere lo stesso, stai confrontando i riferimenti, non i valori sottostanti.

Devi specificare cosa rende due istanze di Board uguali.

Puoi farlo nel tuo 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... 

Oppure puoi farlo nelle tue classi: (nota che ho scritto questo al volo – ti conviene aggiustarlo)

 public class Board { public List Rows = new List(); 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 Cells = new List(); 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 } } 

Ho usato override di getHasCode ed è uguale a, ma non mi è mai piaciuto visto che non voglio modificare il mio codice di produzione per motivi di test delle unità. Inoltre è una specie di dolore.

Poi ho girato troppo il riflesso per confrontare gli oggetti che erano meno invasivi … ma è un sacco di lavoro (molti casi d’angolo)

Alla fine uso:

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

Funziona alla grande.

ExpectedObjects ti aiuterà a confrontare l’uguaglianza in base al valore della proprietà. Supporta:

  1. object semplice: expected.ToExpectedObject (). ShouldEqual (actual);
  2. collection: expected.ToExpectedObject (). ShouldEqual (actual);
  3. object composto: expected.ToExpectedObject (). ShouldEqual (actual);
  4. confronto parziale: l’object previsto necessita di una progettazione con tipo anonimo e utilizza expected.ToExpectedObject (). ShouldMatch (actual)

Amo ExpectedObjects perché ho solo bisogno di invocare 2 API per l’affermazione di confrontare l’uguaglianza degli oggetti:

  1. ShouldEqual ()
  2. ShouldMatch () per il confronto parziale

Volevo una soluzione che non richiedesse l’aggiunta di una dipendenza, funzionasse con i test delle unità VS, confrontasse i valori dei campi di due oggetti e mi dicesse tutti i campi non uguali. Questo è quello che mi è venuto in mente. Nota che potrebbe essere esteso per funzionare anche con valori di proprietà.

Nel mio caso, questo funziona bene per confrontare i risultati di alcune logiche di analisi dei file per garantire che due voci “diverse” tecnicamente abbiano campi con gli stessi valori.

  public class AssertHelper { public static void HasEqualFieldValues(T expected, T actual) { var failures = new List(); 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); } } 

I metodi di asserzione si basano sull’equals dell’object e sul codice GetHash. È ansible implementarlo, ma se questa uguaglianza dell’object non è necessaria al di fuori dei test unitari, prenderei invece in considerazione la possibilità di confrontare i singoli tipi primitivi sull’object. Sembra che gli oggetti siano abbastanza semplici e l’override degli uguali non sia realmente giustificata.