Junit:断言列表至少包含一个与某些条件匹配的属性

问题描述 投票:0回答:4

我有一个方法将返回类型为

MyClass
的对象列表。
MyClass
有很多属性,但我关心
type
count
。我想编写一个测试,断言返回的列表至少包含一个与特定条件匹配的元素。例如,我希望列表中至少有一个类型为
"Foo"
且计数为
1
的元素。

我试图弄清楚如何做到这一点,而不需要逐个循环返回的列表并单独检查每个元素,如果我找到一个通过的元素,则中断,例如:

    boolean passes = false;
    for (MyClass obj:objects){
        if (obj.getName() == "Foo" && obj.getCount() == 1){
            passes = true;
        }
    }
    assertTrue(passes);

我真的不喜欢这个结构。我想知道是否有更好的方法使用

assertThat
和一些 Matcher 来做到这一点。

java unit-testing junit hamcrest
4个回答
5
投票

进口 hamcrest

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

您可以使用

进行测试
    assertThat(foos, hasItem(allOf(
        hasProperty("name", is("foo")),
        hasProperty("count", is(1))
    )));

4
投票
assertTrue(objects.stream().anyMatch(obj ->
    obj.getName() == "Foo" && obj.getCount() == 1
));

或更可能:

assertTrue(objects.stream().anyMatch(obj ->
    obj.getName().equals("Foo") && obj.getCount() == 1
));

1
投票

我不知道是否值得使用 Hamcrest,但很高兴知道它就在那里。

public class TestClass {
    String name;
    int count;

    public TestClass(String name, int count) {
        this.name = name;
        this.count = count;
    }

    public String getName() {
        return name;
    }

    public int getCount() {
        return count;
    }
}

@org.junit.Test
public void testApp() {
    List<TestClass> moo = new ArrayList<>();
    moo.add(new TestClass("test", 1));
    moo.add(new TestClass("test2", 2));

    MatcherAssert.assertThat(moo,
            Matchers.hasItem(Matchers.both(Matchers.<TestClass>hasProperty("name", Matchers.is("test")))
                    .and(Matchers.<TestClass>hasProperty("count", Matchers.is(1)))));
}

0
投票

虽然更冗长,但您可以仅使用 AssertJ 来完成(即不使用 Hamcrest)。使用这些导入:

import static org.assertj.core.api.Assertions.allOf;
import static org.assertj.core.api.Assertions.anyOf;
import static org.assertj.core.api.Assertions.assertThat;
import org.assertj.core.api.Condition;

然后你可以这样断言:

assertThat(foos).haveAtLeastOne(
    allOf(
        new Condition<>(x -> x.getName() == "Foo", ""),
        new Condition<>(x -> x.getCount() == 1, "")));

当您有更复杂的条件并且您更喜欢将每个条件放在自己的行中时,此格式可能会很有用,例如查找至少匹配一组条件的一项:

assertThat(foos).haveAtLeastOne(
    anyOf(
        allOf(
            new Condition<>(x -> x.getName() == "Foo", ""),
            new Condition<>(x -> x.getCount() == 1, "")),
        allOf(
            new Condition<>(x -> x.getName() == "Bar", ""),
            new Condition<>(x -> x.getCount() == 2, ""))));
© www.soinside.com 2019 - 2024. All rights reserved.