【问题标题】:Mockito matcher that compares items in Set, not the Set reference itself比较 Set 中的项目的 Mockito 匹配器,而不是 Set 引用本身
【发布时间】:2015-06-30 05:51:49
【问题描述】:
when(validator.isValid(Sets.newHashSet("valid"))).thenReturn(true);

validator.isValid(set) 被调用时,它返回false。这是因为验证器实现创建了一个新集合,它与传递的集合不同(引用不同) - 两个集合中的项目相同。

如果集合包含相同的项目,无论集合实例如何,我都需要返回 true

类似org.mockito.Matchers的东西:

public static <T> Set<T> anySetOf(Class<T> clazz) {
        return (Set) reportMatcher(Any.ANY).returnSet();
}

除了我传递的实例不是Class&lt;T&gt;.class

verify 也一样:

verify(validator, times(1)).isValid(Sets.newHashSet("valid"));

有这样的匹配器吗?

【问题讨论】:

  • 这是不正确的。如果该方法返回 true 而不是 false,则仅表示实际集合不等于(由 Set.equals() 定义)与Sets.newHashSet("valid")。它内部有更多或更少或不同的元素。所以你不需要任何匹配器。没有匹配器,或者如果集合实际上等于Sets.newHashSet("valid"),则 eq() 匹配器会很好。

标签: java set mockito matcher


【解决方案1】:

显然 JB Nizet 是对的。不需要特定的匹配器。

我尝试使用我自己的匹配器,然后在删除后它也起作用了:

public static class SetItemMatcher extends ArgumentMatcher<Set<String>> {
    public static Set<String> setOf(Set<String> items) {
        return argThat(new SetItemMatcher(items));
    }

    private final Set<String> expected;

    public SetItemMatcher(Set<String> expected) {
        this.expected = expected;
    }

    @Override
    public boolean matches(Object argument) {
        Set<?> actual = (Set<?>) argument;
        return actual.size() == expected.size()  && containsAllItems(actual);
    }

    private boolean containsAllItems(Set<?> actual) {
        for (Object o : actual) {
            if (!expected.contains(o)) {
                return false;
            }
        }
        return true;
    }
}

【讨论】:

    【解决方案2】:

    虽然Felix 的回答是绝对正确的,但我对其稍作修改以涵盖更多用例:

    1. 使用任何集合,而不仅仅是集合。
    2. 添加了实用方法以仅基于一个项目或另一个列表/集创建列表或集
    public class CollectionItemMatcher<T extends Collection> implements ArgumentMatcher<T> {
        public static Set setOf(Object oneItem) {
            return setOf(Sets.newHashSet(oneItem));
        }
    
        public static Set setOf(Collection items) {
            return ArgumentMatchers.argThat(new CollectionItemMatcher<Set>(Sets.newHashSet(items)));
        }
    
        public static List listOf(Object oneItem) {
            return listOf(Lists.newArrayList(oneItem));
        }
    
        public static List listOf(Collection items) {
            return ArgumentMatchers.argThat(new CollectionItemMatcher<List>(Lists.newArrayList(items)));
        }
    
        private final T expected;
    
        public CollectionItemMatcher(T expected) {
            this.expected = expected;
        }
    
        @Override
        public boolean matches(T actual) {
            return actual.size() == expected.size() && containsAllItems(actual);
        }
    
        private boolean containsAllItems(T actual) {
            for (Object o : actual) {
                if (!expected.contains(o)) {
                    return false;
                }
            }
            return true;
        }
    }
    
    

    然后你可以这样做:

    verify(validator, times(1)).isValid(CollectionItemMatcher.setOf("valid"));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 2020-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多