2016-02-26 20 views
5

Ho una struttura di oggetti abbastanza complessa (con un mucchio di campi primitivi e riferimenti a oggetti) e voglio testare tutti i campi tranne - alcuni - di loro. Come esempio;Hamcrest - Un modo elegante per testare oggetti complessi con samepropertyvaluesas

ComplexObject actual = generateMagically("someInput"); 
ComplexObject expected = ActualFunction.instance.workMagically(actual); 

// we want to be sure that workMagically() would create a new ComplexObject 
// with some fields are different than "actual" object. 

// assertThat(actual, samePropertyValuesAs(expected)); would check all fields. 
// what I want is actually; - notice that "fieldName1" and "fieldName2" are 
// primitives belong to ComplexObject 
assertThat(actual, samePropertyValuesExceptAs(expected, "fieldName1", "fieldName2")) 

Dal momento che non voglio controllare tutti i campi manualmente, credo che ci deve essere un modo di scrivere che prova con eleganza. Qualche idea?

Cheers.

+0

modo da avere due oggetti * * bag e desidera eseguire il confronto profondo? – Raffaele

+0

Non è sicuro chiamarli oggetto bag, ha molti campi primitivi e altri riferimenti a oggetti. I campi che voglio saltare sono quelli primitivi che appartengono a ComplexObject. Possiamo dire che sarà un confronto profondo. – tugcem

+0

Vuoi solo l'implementazione di Matcher per 'samePropertyValuesExceptAs' come risposta a questa domanda? In tal caso, è sufficiente creare una copia di 'org.hamcrest.beans.SamePropertyValuesAs ' e aggiungervi un altro costruttore/metodo factory statico che rimuoverà le proprietà escluse dalla fase di test. – SpaceTrucker

risposta

0

In generale, vedo due soluzioni se ComplexObject può essere modificato da solo.

È possibile introdurre un'interfaccia che rappresenta le proprietà di ComplexObject che vengono modificate da ActualFunction. Quindi puoi verificare che tutte le proprietà di quella nuova interfaccia siano cambiate. Ciò richiederebbe che ComplexObject implementasse quella nuova interfaccia.

Un altro approccio sarebbe quello di sostituire le proprietà di ComplextObject che vengono modificate da ActualFunction con una nuova proprietà di un nuovo tipo che contiene tutte quelle proprietà. Un progetto migliore dovrebbe quindi consentire a ActualFunction di restituire un'istanza del nuovo tipo.

+0

Grazie SpaceTrucker. (1 Penso che implementare un'interfaccia nell'oggetto di dominio solo per scopi di test non sia una best practice. (2) Per un altro approccio, in realtà offri di aggiungere una nuova proprietà (presumo un nuovo oggetto) che ha proprietà aggiornate?Cambiando nuovamente l'oggetto solo per il test, immagino di no. – tugcem

+0

@tugcem non si tratta solo di test, si tratta di rendere gli effetti di 'ActualFunction' più visibili e la funzione che rappresenta più espressiva. Ad esempio, se l'implementazione di "ActualFunction" cambierebbe anche per modificare un'altra proprietà, l'effetto sarebbe immediatamente visibile se si utilizza il mio secondo approccio perché il nuovo tipo otterrebbe quella nuova proprietà. – SpaceTrucker

+0

In realtà non è necessario inserire espressioni o visibilità extra per la funzione workMagically() relativa alla modifica delle proprietà. Infatti, non vogliamo dire nulla di esplicito sui campi aggiornati e ci aspettiamo che gli utenti di questa classe ne siano consapevoli. – tugcem

0

L'ultima volta che ho avuto requisiti simili sono giunto alla conclusione che scrivere manualmente sia il codice che i test per affermare che alcuni valori sono aggiornati è intrinsecamente fagile e soggetto a errori.

Ho esternalizzato i campi in un oggetto borsa e generato i file di origine Java sia per la classe bag che per la fotocopiatrice in fase di compilazione. In questo modo puoi testare il codice attuale (il generatore) e avere la definizione effettiva del dominio esattamente in un punto, in modo che il codice della copia non possa essere scaduto.

Il linguaggio per descrivere la proprietà può essere qualsiasi cosa hai dimestichezza con, da JSON-schema di XML per Java stesso (Java esempio segue - le annotazioni personalizzate devono essere consumate dal generatore)

public class MyBag { 
    @Prop public int oh; 
    @Prop public String yeah; 
} 
7

È dovrebbe dare un'occhiata a shazamcrest, una grande estensione Hamcrest che offre quello che ti serve.

assertThat(expected, sameBeanAs(expectedPerson).ignoring("fieldName1").ignoring("fieldName2")); 

Vedi https://github.com/shazam/shazamcrest#ignoring-fields

+1

Se qualcuno si chiede dove '' 'sameBeanAs''' sia, è nella classe ' '' com.shazam.shazamcrest.matcher.Matchers'''. –

Problemi correlati