当前位置: 首页 > 知识库问答 >
问题:

Hamcrest:如何为匹配器进行实例化和强制转换?

姜晨
2023-03-14
@Test
public void test() throws Exception {
    Object value = 1;
    assertThat(value, greaterThan(0));
}

简单的解决方案是通过像这样强制转换匹配器来删除泛型:

assertThat(value, (Matcher)greaterThan(0));

可能,但会生成编译器警告并感觉错误。

一个冗长的替代方案是:

@Test
public void testName() throws Exception {
    Object value = 1;

    assertThat(value, instanceOfAnd(Integer.class, greaterThan(0)));
}

private static<T> Matcher<Object> instanceOfAnd(final Class<T> clazz, final Matcher<? extends T> submatcher) {
    return new BaseMatcher<Object>() {
        @Override
        public boolean matches(final Object item) {
            return clazz.isInstance(item) && submatcher.matches(clazz.cast(item));
        }

        @Override
        public void describeTo(final Description description) {
            description
                .appendText("is instanceof ")
                .appendValue(clazz)
                .appendText(" and ")
                .appendDescriptionOf(submatcher);
        }

        @Override
        public void describeMismatch(final Object item, final Description description) {
            if (clazz.isInstance(item)) {
                submatcher.describeMismatch(item, description);
            } else {
                description
                    .appendText("instanceof ")
                    .appendValue(item == null ? null : item.getClass());
            }
        }
    };
}
Map<String, Object> map = executeMethodUnderTest();
assertThat(map, hasEntry(equalTo("the number"), greaterThan(0)));

共有1个答案

强德厚
2023-03-14

这个答案不会显示如何使用Hamcrest这样做,我不知道是否有比建议的更好的方法。

但是,如果您有可能包括另一个测试库,那么AssertJ完全支持以下内容:

import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class TestClass {

  @Test
  public void test() throws Exception {
    Object value = 1;
    assertThat(value).isInstanceOfSatisfying(Integer.class, integer -> assertThat(integer).isGreaterThan(0));
  }

}

不需要任何强制转换,AssertJ为您完成此操作。

java.lang.AssertionError:
Expecting:
 <0>
to be greater than:
 <0> 
java.lang.AssertionError: 
Expecting:
 <"not an integer">
to be an instance of:
 <java.lang.Integer>
but was instance of:
 <java.lang.String>
// second constructor parameter is the light saber color
Object yoda = new Jedi("Yoda", "Green");
Object luke = new Jedi("Luke Skywalker", "Green");

Consumer<Jedi> jediRequirements = jedi -> {
  assertThat(jedi.getLightSaberColor()).isEqualTo("Green");
  assertThat(jedi.getName()).doesNotContain("Dark");
};

// assertions succeed:
assertThat(yoda).isInstanceOfSatisfying(Jedi.class, jediRequirements);
assertThat(luke).isInstanceOfSatisfying(Jedi.class, jediRequirements);

// assertions fail:
Jedi vader = new Jedi("Vader", "Red");
assertThat(vader).isInstanceOfSatisfying(Jedi.class, jediRequirements);
// not a Jedi !
assertThat("foo").isInstanceOfSatisfying(Jedi.class, jediRequirements);
 类似资料:
  • 输入: null 目标是使以下语句可编译: 这里有什么用?它想让我<编码>匹配器<?super java.util.list >并告诉我通过了 。那么如何在这里传递匹配器集合呢? 有一个关于将集合与hamcrest进行比较的问题,但没有传递Matchers集合的示例,而不是元素。

  • 它看起来像hamcrest(尽管看起来,还有更多)。为什么我会选择使用(除了看起来类稍微小一点之外),为什么这两个类如此相似?

  • 我试图使用JUnit/Hamcrest断言集合至少包含一个自定义逻辑断言为true的元素。我希望有像“anyOf”这样的匹配器,它采用lambda(或匿名类定义),在这里我可以定义自定义逻辑。我试过TypeSafeMatcher,但不知道该怎么处理它。 我不认为任何一个是我想要的,因为这似乎需要一个匹配者的名单。

  • 我需要检查是否一个url是有效的和空值是可接受的以及。我是这个图书馆的新手,被这个错误难倒了。

  • 我想在TestNG测试中使用Hamcrest匹配器,特别是软断言。我怎么能这么做?我知道我可以在测试中使用Hamcrest的断言,例如:

  • 我的问题是:这是一个bug还是我遗漏了什么? 事实上,不同的匹配器以不同的格式返回消息是一个很大的问题,因为我试图编写一些自定义的验证框架,该框架使用匹配器,并且能够在出现任何错误时返回良好的人类可读的消息。我似乎不能为此目的使用方法...