Есть ли способ создать статический метод, который будет возвращать сопоставитель Hamcrest, который соответствует коллекции или соответствует нулю?

Я пытаюсь внедрить сопоставители Hamcrest в код моей команды. Чтобы упростить сопоставление коллекции экземпляров, я хочу написать вспомогательный метод для каждого из моих сопоставителей, которые, как я ожидаю, будут желательны для сопоставления коллекций. Так что, по сути, я оборачиваю containsInAnyOrder. При этом, если кто-то передает значение null как ожидаемое и фактическое, я хочу, чтобы оно совпадало. Но так, как я написал свой код, он выдаст исключение NullPointerException, если для ожидаемого будет передано значение null. Итак, я хочу вернуть сопоставитель IsNull, если null передан как и ожидалось. Вот мой пример кода:

/**
 * Matches all Foo objects in an order agnostic manner.
 * @param expected The collection of Foo objects to be matched.
 * @return A matcher that will match a collection of Foos
 */
@SuppressWarnings("unchecked")
public static Matcher<Iterable<? extends Foo>> matchesAllfoos(Collection<Foo> expected)
{
    if (expected == null)
    {
        // Doesn't work because Matcher<Iterable> is not a Matcher<Iterable<? extends Foo>>
        return nullValue(Iterable.class);
    }

    // The cast is here to provide a hint to Java as to which overloaded method to choose.
    // See http://stackoverflow.com/questions/18614621/conflicting-overloads-for-hamcrest-matcher
    return containsInAnyOrder((Collection)Collections2.transform(expected, FOO_TO_MATCHER));
}

Итак, как мне добиться того, что я хочу сделать? Использование nullValue() не работает, потому что тогда ожидается, что я верну Matcher. Кастинг nullValue(Iterable.class) не работает. Есть идеи?


person Jason Thompson    schedule 14.01.2014    source источник


Ответы (1)


Если присмотреться, nullValue(Class<T>) просто создает IsNull<T> сопоставитель.

Итак, если вы звоните:

public static <T> Matcher<T> nullValue(Class<T> type) {
    return new IsNull<T>();
}

В конце концов (поскольку дженерики доставляют массу неудобств, потому что вы не можете определить класс среды выполнения потенциально null объекта), вы можете просто вызвать конструктор напрямую:

new IsNull<Iterable<? extends Foo>>();

Таким образом, решением было бы просто использовать его без вспомогательного метода nullValue():

/**
 * Matches all Foo objects in an order agnostic manner.
 * @param expected The collection of Foo objects to be matched.
 * @return A matcher that will match a collection of Foos
 */
@SuppressWarnings("unchecked")
public static Matcher<Iterable<? extends Foo>> matchesAllfoos(Collection<Foo> expected)
{
    if (expected == null)
    {
        return new IsNull<Iterable<? extends Foo>>();
    }

    // The cast is here to provide a hint to Java as to which overloaded method to choose.
    // See http://stackoverflow.com/questions/18614621/conflicting-overloads-for-hamcrest-matcher
    return containsInAnyOrder((Collection)Collections2.transform(expected, FOO_TO_MATCHER));
}
person acdcjunior    schedule 15.01.2014
comment
Конечно! Я даже не подумал посмотреть, являются ли классы общедоступными, поскольку я обычно делаю свои конструкторы Matcher закрытыми. - person Jason Thompson; 16.01.2014