2016-02-26 9 views
5

Mam dość złożoną strukturę obiektu (z paczką prymitywnych pól i odniesień do obiektów) i chcę przetestować wszystkie pola z wyjątkiem-kilka z nich. Jako przykład;Hamcrest - Elegancki sposób testowania złożonego obiektu z 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")) 

Ponieważ nie chcę ręcznie sprawdzać wszystkich pól, uważam, że musi istnieć sposób na eleganckie napisanie tego testu. Jakieś pomysły?

Pozdrawiam.

+0

Więc masz dwie torby * * obiektów i chcą wykonywać głębokie porównania? – Raffaele

+0

Nie można nazywać ich obiektami torby, ma wiele prymitywnych pól i inne odwołania do obiektów. Pola, które chcę pominąć, są prymitywne należą do ComplexObject. Możemy powiedzieć, że będzie to głębokie porównanie. – tugcem

+0

Po prostu chcesz, aby implementacja Matchera dla 'samePropertyValuesExceptAs' była odpowiedzią na to pytanie? Jeśli tak, to możesz po prostu utworzyć kopię 'org.hamcrest.beans.SamePropertyValuesAs ' i dodać do niej inną metodę konstruktora/statycznej fabryki, która usunie wykluczone właściwości z testowania. – SpaceTrucker

Odpowiedz

0

Ogólnie widzę dwa rozwiązania, jeśli ComplexObject może być modyfikowany przez siebie.

Można wprowadzić interfejs reprezentujący właściwości ComplexObject, które są zmieniane przez ActualFunction. Następnie możesz przetestować, czy zmieniły się wszystkie właściwości tego nowego interfejsu. Wymagałoby to, aby ComplexObject zaimplementował ten nowy interfejs.

Innym podejściem byłoby zastąpienie właściwości ComplextObject zmienionych przez ActualFunction nową właściwością nowego typu, która zawiera wszystkie te właściwości. Lepszym rozwiązaniem byłoby wtedy, aby ActualFunction zwrócił instancję nowego typu.

+0

Dzięki SpaceTrucker. (1) Myślę, że implementacja interfejsu w obiekcie domeny tylko dla celów testowych nie jest najlepszą praktyką. (2) W przypadku innego podejścia, faktycznie proponujesz dodanie nowej właściwości (zakładam nowy obiekt), która zaktualizowała właściwości?Ponownie zmieniając obiekt tylko do testowania, chyba nie. – tugcem

+0

@tugcem nie chodzi tylko o testowanie, chodzi o to, aby efekty "ActualFunction" były bardziej widoczne, a funkcja, którą reprezentuje, jest bardziej wyrazista. Na przykład, jeśli implementacja 'ActualFunction' zmieniłaby się, aby zmodyfikować inną właściwość, niż efekt byłby natychmiast widoczny, gdyby używał mojego drugiego podejścia, ponieważ nowy typ otrzymywałby tę nową właściwość. – SpaceTrucker

+0

Właściwie nie potrzebuję dodawać dodatkowej ekspresji ani widoczności do funkcji workMagically() o zmianie właściwości. W rzeczywistości nie chcemy mówić niczego konkretnego o zaktualizowanych polach i oczekiwać, że użytkownicy tej klasy będą tego świadomi. – tugcem

0

Ostatnim razem, gdy miałem podobne wymagania, doszedłem do wniosku, że ręczne pisanie zarówno kodu, jak i testów potwierdzających, że niektóre wartości są aktualizowane, jest z natury podatne na błędy i podatne na błędy.

Uzewnętrzniłem pola w obiekcie torby i wygenerowałem pliki źródłowe Java dla samej klasy worka i kopiarki w czasie kompilacji. W ten sposób możesz przetestować aktualny kod (generator) i mieć faktyczną definicję domeny w dokładnie jednym miejscu, więc kod kopiowania nie może być nieaktualny.

Językiem opisać nieruchomość może być cokolwiek, że są wygodne z, z JSON-schematu XML do samego Java (Java przykład następująco - niestandardowe adnotacje powinny być spożywane z generatora)

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

You powinieneś rzucić okiem na shazamcrest, świetne rozszerzenie Hamcrest, które oferuje to, czego potrzebujesz.

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

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

+1

Jeśli ktoś się zastanawia, gdzie jest '' ten samBeanAs''', jest on w klasie '' 'com.shazam.shazamcrest.matcher.Matchers'''. –

Powiązane problemy