【问题标题】:What's the right signature for a custom matcher for an Iterable?Iterable 的自定义匹配器的正确签名是什么?
【发布时间】:2015-10-08 10:48:09
【问题描述】:

我正在尝试为具有 Iterable 字段的类编写自定义匹配器。我想不出办法让它可以接受任何匹配器 everyItemhasItemcontains - 因为每个其中返回稍微不同的泛型类型。最好的方法是什么?

这里有一个简单的例子来演示这个问题 - 我怎样才能让它编译?我正在使用 Hamcrest 1.3。

import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.everyItem;
import static org.hamcrest.Matchers.hasItem;
import static org.junit.Assert.assertThat;

import java.util.Collection;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;

    public class MatcherExample {

        public static class Band {
            public Collection<Member> getMembers() {
                return null;
            }
        };

        public static class Member {
        };

        public static Matcher<Band> hasMembers(final Matcher<Iterable<Member>> matcher) {
            return new TypeSafeDiagnosingMatcher<Band>() {
                @Override
                public void describeTo(Description description) {
                }

                @Override
                protected boolean matchesSafely(Band item, Description mismatchDescription) {
                    return matcher.matches(item.getMembers());
                }
            };

        }

        public static void main(String[] args) {
            Band band = new Band();
            assertThat(band, hasMembers(everyItem(equalTo(new Member())))); // works with signature Matcher<Iterable<Member>>
            assertThat(band, hasMembers(hasItem(equalTo(new Member()))));   // works with signature Matcher<Iterable<? super Member>>
            assertThat(band, hasMembers(contains(equalTo(new Member()))));  // works with signature Matcher<Iterable<? extends Member>>
        }
    }

【问题讨论】:

    标签: java generics matcher hamcrest


    【解决方案1】:

    以下签名对我有用:

    public static Matcher<Band> hasMembers(final Matcher<? super Iterable<Member>> matcher) {
        // ...
    }
    

    旁注:

    Hamcrest 有 FeatureMatcher 类可以轻松地为特定属性创建匹配器:

    public static Matcher<Band> hasMembers(final Matcher<? super Iterable<Member>> matcher) {
        return new FeatureMatcher<Band, Iterable<Member>>(matcher, "a band with members", "members") {
    
            @Override
            protected Iterable<Member> featureValueOf(Band actual) {
                return actual.getMembers();
            }
        };
    };
    

    【讨论】:

      【解决方案2】:

      非常棘手的问题。只能让它对前两个起作用(everyItemhasItem

      public static <M extends Member, B extends Band, I extends Iterable<? super M>> Matcher<B> hasMembers(
              final Matcher<I> matcher) {
          return new TypeSafeDiagnosingMatcher<B>() {
              @Override
              public void describeTo(Description description) {
              }
      
              @Override
              protected boolean matchesSafely(B item, Description mismatchDescription) {
                  return matcher.matches(item.getMembers());
              }
          };
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-14
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 2014-08-04
        • 2014-12-14
        • 1970-01-01
        相关资源
        最近更新 更多