2014-09-03 22 views
10

hasProperty może być używany z hasItem celu sprawdzenia wartości danej nieruchomości, np:Hamcrest dopasowujący do sprawdzania wartości zwracanej przez metodę w kolekcji

Matcher hasName = Matchers<Person>hasProperty("name", is("Winkleburger")); 
assertThat(names, hasItem(hasName)); 

Jest to dobre rozwiązanie, gdy nazwa jest nieruchomość, to znaczy: nie to metoda o nazwie getName().

Czy istnieje narzędzie sprawdzające metodę, która nie jest własnością? tj: w tym przypadku sprawdzi wartość zwracaną metody name() zamiast getName(), dla elementów w kolekcji.

+0

, więc chcesz wywołać metodę name() we wszystkich elementach kolekcji? –

Odpowiedz

12

Możesz użyć innego wbudowanego Hamcrest do tego, FeatureMatcher. Są one zaprojektowane tak, aby można je było łączyć z innymi elementami dopasowującymi po przekształceniu danych wejściowych w coś innego. Więc w twoim przypadku byłoby zrobić coś takiego:

@Test 
public void test1() { 
    List<Person> names = new ArrayList<>(); 
    names.add(new Person("Bob")); 
    names.add(new Person("i")); 

    assertThat(names, hasItem(name(equalTo("Winkleburger")))); 
} 

private FeatureMatcher<Person, String> name(Matcher<String> matcher) { 
    return new FeatureMatcher<Person, String>(matcher, "name", "name") { 
     @Override 
     protected String featureValueOf(Person actual) { 
      return actual.name(); 
     } 
    }; 
} 

Korzyść dostaniesz z tego ponad niestandardowym dopasowującego jest to, że w pełni wielokrotnego użytku i composable z innymi dopasowujących jak wszystko co robi to dane ekstrakcja następnie odradza się do dowolnego innego, jakiego chcesz. Otrzymasz także odpowiednią diagnostykę, np. w powyższym przykładzie, jeśli zmienisz assert na wartość, która nie jest obecna, otrzymasz:

java.lang.AssertionError: 
    Expected: a collection containing name "Batman" 
    but: name was "Bob", name was "Winkleburger" 
2

można napisać samemu:

public class HasName extends TypeSafeMatcher<MyClass> { 
    private String expectedName; 

    private HasName(String expectedName) { 
     this.expectedName = expectedName; 
    } 

    @Override 
    public boolean matchesSafely(MyClass obj) { 
     return expectedName.equals(obj.name()); 
    } 

    @Factory 
    public static Matcher<MyClass> hasName(String expectedName) { 
     return new HasName(expectedName); 
    } 
} 

Gdzie MyClass jest klasa lub interfejs który definiuje metodę name().