Java 如何断言集合中的集合包含包含特定元素的元素?

Java 如何断言集合中的集合包含包含特定元素的元素?,java,unit-testing,junit,hamcrest,assertj,Java,Unit Testing,Junit,Hamcrest,Assertj,假设我有Strings“foo”,“bar”和baz 我得到了一个候选流 现在我想断言候选中的所有元素都是元组,包含{“foo”,“bar”}(以任何顺序)或{“bar”,“baz”}(以任何顺序) 如何最好地做到这一点?第一步是使用Stream#allMatch(谓词)检查元组中[foo,bar]或[bar,baz]的组合以及元组的大小 在第二步中,我将内部数组转换为一个集合,这样就可以很容易地解决类似[foo,foo]的情况,因为重复项将被删除,而且我们还可以使用Set.contains()

假设我有
String
s
“foo”
“bar”
baz

我得到了一个
候选流

现在我想断言
候选中的所有元素都是元组,包含
{“foo”,“bar”}
(以任何顺序)或
{“bar”,“baz”}
(以任何顺序)


如何最好地做到这一点?

第一步是使用
Stream#allMatch(谓词)
检查元组中
[foo,bar]
[bar,baz]
的组合以及元组的大小

在第二步中,我将内部数组转换为一个
集合
,这样就可以很容易地解决类似
[foo,foo]
的情况,因为重复项将被删除,而且我们还可以使用
Set.contains()
进行O(1)查找,以检查
[foo,bar]
[bar,baz]
存在于元组流中:

class TupleTest {

@org.junit.jupiter.api.Test
void testTupleOfCandidates_True() {
    Stream<String[]> candidates = Stream.of(new String[]{"bar", "foo"}, new String[]{"bar", "baz"});
    assertTrue(isCandidateStreamValid(candidates));

    candidates = Stream.of(new String[]{"bar", "foo"}, new String[]{"bar", "baz"});
    assertTrue(isCandidateStreamValid(candidates));

}

@org.junit.jupiter.api.Test
void testTupleOfCandidates_False() {
    Stream<String[]> candidates = Stream.of(new String[]{"foo", "foo"}, new String[]{"bar", "baz"});
    assertFalse(isCandidateStreamValid(candidates));

    candidates = Stream.of(new String[]{"bar", "foo"}, new String[]{"bar", "baz"}, new String[]{"baz", "bar"});
    assertTrue(isCandidateStreamValid(candidates));
}

public boolean isCandidateStreamValid(Stream<String[]> candidates){
        return candidates.allMatch(arr -> {
            Set<String> data = new HashSet(Arrays.asList(arr));
            return data.size() == 2
                    &&
                    ((data.contains("foo") && data.contains("bar"))
                            ||
                            (data.contains("bar") && data.contains("baz")));
        });
    }
}
class-TupleTest{
@org.junit.jupiter.api.Test
void testTupleOfCandidates_True(){
候选流=Stream.of(新字符串[]{“bar”,“foo”},新字符串[]{“bar”,“baz”});
assertTrue(isCandidateStreamValid(候选者));
候选项=Stream.of(新字符串[]{“bar”,“foo”},新字符串[]{“bar”,“baz”});
assertTrue(isCandidateStreamValid(候选者));
}
@org.junit.jupiter.api.Test
void testTupleOfCandidates_False(){
候选流=Stream.of(新字符串[]{“foo”,“foo”},新字符串[]{“bar”,“baz”});
assertFalse(isCandidateStreamValid(候选者));
候选项=Stream.of(新字符串[]{“bar”,“foo”},新字符串[]{“bar”,“baz”},新字符串[]{“baz”,“bar”});
assertTrue(isCandidateStreamValid(候选者));
}
公共布尔值isCandidateStreamValid(流候选){
返回候选者。所有匹配(arr->{
Set data=newhashset(Arrays.asList(arr));
返回数据。大小()==2
&&
((data.contains(“foo”)和&data.contains(“bar”))
||
(数据包含(“baz”)&数据包含(“baz”);
});
}
}

为了简单起见,我将创建一个可以验证元组的函数。将对流中的每个元素调用此函数。我还将创建第二个函数,用于检查一个数组是否包含另一个数组的每个元素。大概是这样的:

import org.junit.Test;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;

public class MyTest {

    @Test
    public void test(){
        Stream<String[]> stream = Stream.of(new String[]{"foo", "bar"}, new String[]{"bar", "baz"});
        stream.forEach(arr -> assertThat(validTuple(arr)).isTrue());

        //Order does not matter:
        stream = Stream.of(new String[]{"bar", "foo"}, new String[]{"baz", "bar"});
        stream.forEach(arr -> assertThat(validTuple(arr)).isTrue());

        //Invalid tuples
        stream = Stream.of(new String[]{"foo", "asdf"}, new String[]{"foo", "baz"});
        stream.forEach(arr -> assertThat(validTuple(arr)).isFalse());
    }

    private boolean validTuple(String[] array){
        if(array.length != 2) return false;
        return containsAll(array, "foo", "bar") || containsAll(array, "bar", "baz");
    }

    private boolean containsAll(String[] array, String... values){
        for (String value : values) {
            boolean containsValue = false;
            for (String s : array) {
                if(s.equals(value)){
                    containsValue = true;
                    break;
                }
            }
            if(!containsValue){
                return false;
            }
        }

        return true;
    }

}
import org.junit.Test;
导入java.util.stream.stream;
导入静态org.assertj.core.api.Assertions.assertThat;
公共类MyTest{
@试验
公开无效测试(){
Stream-Stream=Stream.of(新字符串[]{“foo”,“bar”},新字符串[]{“bar”,“baz”});
stream.forEach(arr->assertThat(validTuple(arr)).isTrue();
//顺序无关紧要:
stream=stream.of(新字符串[]{“bar”,“foo”},新字符串[]{“baz”,“bar”});
stream.forEach(arr->assertThat(validTuple(arr)).isTrue();
//无效元组
stream=stream.of(新字符串[]{“foo”,“asdf”},新字符串[]{“foo”,“baz”});
stream.forEach(arr->assertThat(validTuple(arr)).isFalse();
}
私有布尔有效整数(字符串[]数组){
如果(array.length!=2)返回false;
返回containsAll(数组,“foo”,“bar”)| containsAll(数组,“bar”,“baz”);
}
私有布尔containsAll(字符串[]数组,字符串…值){
for(字符串值:值){
布尔值containsValue=false;
for(字符串s:数组){
如果(s.等于(值)){
containsValue=true;
打破
}
}
如果(!containsValue){
返回false;
}
}
返回true;
}
}

现在,您可以轻松地将这些方法提取到一个专用类中,以便在需要时在其他测试中重复使用它们。

您可以使用
allMatch
allsummit
之类的方法

assertThat(candidates).allMatch(candidate -> candidate.contains...)


比如说,
{“foo”,“foo”}
,这将失败。(您还忘了检查
arr
的大小是否为2,顺便说一句。)@User1291感谢您捕捉到了这一点,我修复了我之前发布的代码,它应该适用于所有情况。如果我们继续这样做,我建议将您的函数设置为
谓词
,并使用
stream.allMatch(validTuple)
assertThat(candidates).allSatisfy(
          candidate -> assertThat(candidate).satisfiesAnyOf(
                       c -> {      
                          c.contains("foo");
                          c.contains("bar");
                       },
                       c -> {      
                          c.contains("bar");
                          c.contains("baz");
                       })                                     
         );