【问题标题】:Look for a property in List of object using Hamcrest matcher使用 Hamcrest 匹配器在对象列表中查找属性
【发布时间】:2017-03-30 17:54:51
【问题描述】:

我有一个 Java POJO。

public class Emp {    
    private String name;
    private int id;
}

我有一份员工名单(目标):

 List<Emp> target = new ArrayList<Emap>();
 // Add emp object in list
 assertThat(target, containsInAnyOrder(????));

containsInAnyOrder 中,我必须使用类似 hasProperty("name" , is(equalTo("John")) 的东西。我必须检查列表中的特定属性以获取特定值那么语法应该是什么。我没有找到任何带有对象列表的“containsInAnyOrder”示例。

【问题讨论】:

  • 问题出在哪里?
  • 好的,你得到了一些更新;但也许您会发现其他答案更有帮助。无论如何,你现在已经得到了很多信息......应该足以让你继续前进。

标签: java unit-testing junit matcher hamcrest


【解决方案1】:

如果您的对象比较总是像 Java Pojo 一样简单,那么也许您可以看看来自 Apache Commons Lang3 的 EqualsBuilder。特别是这种方法:

public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients)

您可以实现自己的“等于”匹配器,它将比较委托给reflectionEquals

为此,您从 Hamcrest 继承 TypeSafeDiagnosingMatcher&lt;T&gt; 类。

class ReflectiveEqualsMatcher<T> extends TypeSafeDiagnosingMatcher<T> {

    private final T other;

    public ReflectiveEqualsMatcher(T divisor) {
        this.other = divisor;
    }

    @Override
    protected boolean matchesSafely(T me, Description description) {
        return EqualsBuilder.reflectionEquals(me, other, true);
    }

    @Override
    public void describeTo(Description description) {
    }

    public static <T> ReflectiveEqualsMatcher<T> same(T other) {
        return new ReflectiveEqualsMatcher(other);
    }
}

使用它:

//static import ReflectiveEqualsMatcher.same first
assertThat(target, containsInAnyOrder(same(obj1), same(obj2), same(obj3)));

【讨论】:

    【解决方案2】:

    我知道您想要一个“通用”的东西,例如:迭代整个列表;然后通过name检索对象的字段;然后检查任何元素是否有匹配的东西。

    我认为在 Hamcrest 中没有这样的东西:因为这对于预定义的匹配器来说太复杂了。

    从这个意义上说,这个要求的唯一“答案”是创建您的自己的客户matcher,使用反射来实际做到这一点。

    更多详细信息:您可以从我的旧版answer 开始,其中包含适用于列表的即用型匹配器。

    实际上,现在唯一要做的事情是:更改我的列表匹配器以执行不同类型的检查。在那里,您可以使用另一个答案中列出的 Apache Commons EqualsBuilder。

    在实施上应该没有太大的障碍;它只是“工作”。

    但是:我不确定这是否真的是正确的方法。如前所述;您试图在那里解决的问题听起来对我来说非常具体;而且您知道:任何使用反射的单元测试都缺少任何“基于反射”的代码所具有的相同问题——当有人更改您的生产代码时,编译器不会告诉您;例如通过更改字段名称name

    因此:我宁愿在“生产代码”方面妥协,而不是使用反射;例如通过添加一个简单的 getter:

    public class Emp {
    ... fields
      String getName() { return name; }
    

    而不是使用反射来比较通用属性,您编写一个匹配器,它知道使用该 getter 来获取名称并比较它们。h

    【讨论】:

    • 是的,请。我认为它应该存在。帮帮我。
    猜你喜欢
    • 2015-09-15
    • 2023-04-08
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多