断言Junit中的List

Kam*_*mal 147 java collections junit unit-testing

如何在JUnit测试用例中对列表进行断言?不仅列表的大小,而且列表的内容.

dje*_*kyb 150

我意识到这是几年前被问到的,可能这个功能不是那时候的.但是现在,这很容易做到:

@Test
public void test_array_pass()
{
  List<String> actual = Arrays.asList("fee", "fi", "foe");
  List<String> expected = Arrays.asList("fee", "fi", "foe");

  assertThat(actual, is(expected));
  assertThat(actual, is(not(expected)));
}
Run Code Online (Sandbox Code Playgroud)

如果您使用hamcrest安装了最新版本的Junit,只需添加以下导入:

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
Run Code Online (Sandbox Code Playgroud)

http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T,org.hamcrest.Matcher)

http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html

http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html

  • `System.out.println(actual == expected);`将返回false,但是`System.out.println(actual.equals(expected));`将返回true. (3认同)
  • 这比 assertEquals 好在哪里? (3认同)
  • @Raedwald 断言失败时的输出。我稍后会尝试回来编辑差异。hamcrest 匹配器可以生成详细的失败消息。junit 可以简单地重载assertEquals 以获得类似的好处。但大多数情况下,junit 提供了核心单元测试功能,而 hamcrest 提供了一个很好的对象差异描述器库。 (2认同)

小智 26

不要转换为字符串并进行比较.这对性能不利.在junit中,在Corematchers中,有一个匹配器=>hasItems

List<Integer> yourList = Arrays.asList(1,2,3,4)    
assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5));
Run Code Online (Sandbox Code Playgroud)

这是我知道检查列表中元素的更好方法.

  • _“这对性能不好。” _→我不确定在编写_unit tests_时应该考虑什么程度的性能...但是可以肯定的是,通过`toString()`版本比较字符串不是最好的道路。 (3认同)
  • 应该是选择的答案,但要注意:您还需要验证列表中除了所需内容之外没有其他项目。可能使用:`Assert.assertEquals(4,yourList.size());` (2认同)

Bar*_*ers 20

这是一个传统的答案,适用于JUnit 4.3及更低版本.现代版本的JUnit在assertThat方法中包含内置的可读失败消息.如果可能,请优先考虑此问题的其他答案.

List<E> a = resultFromTest();
List<E> expected = Arrays.asList(new E(), new E(), ...);
assertTrue("Expected 'a' and 'expected' to be equal."+
            "\n  'a'        = "+a+
            "\n  'expected' = "+expected, 
            expected.equals(a));
Run Code Online (Sandbox Code Playgroud)

作为记录,正如@Paul在他对这个答案的评论中提到的,两个List是相同的:

当且仅当指定的对象也是列表时,两个列表具有相同的大小,并且两个列表中的所有对应的元素对相等.(两个元素e1,e2如果相等则相等(e1==null ? e2==null : e1.equals(e2)).)换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等.此定义确保equals方法在List接口的不同实现中正常工作.

请参阅界面JavaDocsList.


dav*_*xxx 14

assertEquals(Object, Object)从JUnit4 / JUnit 5或 assertThat(actual, is(expected));在其他答案中提出的Hamcrest只能同时使用,equals()并且toString()被比较对象的类(并深入)覆盖。

这很重要,因为断言中的相等性测试依赖于equals()并且测试失败消息依赖于toString()比较对象。
对于诸如的内置类StringInteger对于...等等,没有问题,因为它们覆盖了equals()toString()。因此断言List<String>List<Integer>与 完全正确assertEquals(Object,Object)
关于此问题:您必须equals()在类中重写,因为在对象相等性方面它是有意义的,不仅要使使用JUnit进行测试时的断言更容易。
为了使声明更容易,您可以使用其他方法。
作为一个好习惯,我赞成断言/匹配器库。

这是一个AssertJ解决方案。

org.assertj.core.api.ListAssert.containsExactly() 就是您所需要的:它按照Javadoc中的说明,验证实际组是否恰好包含给定的值,并且没有其他内容。

假设有一个Foo类,您可以在其中添加元素并从中获取元素。对此
的单元测试Foo断言这两个列表具有相同的内容,可能类似于:

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception { 
   Foo foo = new Foo();
   foo.add("One", "Two", "Three");
   Assertions.assertThat(foo.getElements())
             .containsExactly("One", "Two", "Three");
}
Run Code Online (Sandbox Code Playgroud)

AssertJ的一个优点List是不需要按预期声明a :它使断言更直接,代码更易读:

Assertions.assertThat(foo.getElements())
         .containsExactly("One", "Two", "Three");
Run Code Online (Sandbox Code Playgroud)

但是断言/匹配器库是必须的,因为它们确实会进一步发展。
假设现在Foo 不存储String秒,但Barš实例。
这是非常普遍的需求。使用AssertJ,断言仍然很容易编写。更好的是,您可以断言列表内容是相等的,即使equals()/hashCode()在JUnit方法要求的情况下不覆盖元素的类:

import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception {
    Foo foo = new Foo();
    foo.add(new Bar(1, "One"), new Bar(2, "Two"), new Bar(3, "Three"));
    Assertions.assertThat(foo.getElements())
              .extracting(Bar::getId, Bar::getName)
              .containsExactly(tuple(1, "One"),
                               tuple(2, "Two"),
                               tuple(3, "Three"));
}
Run Code Online (Sandbox Code Playgroud)


mic*_*alk 13

对于 JUnit 5

你可以使用assertIterableEquals

List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");

Assertions.assertIterableEquals(numbers, numbers2);
Run Code Online (Sandbox Code Playgroud)

assertArrayEquals将列表转换为数组:

List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");
Assertions.assertArrayEquals(numbers.toArray(), numbers2.toArray());
Run Code Online (Sandbox Code Playgroud)


Vik*_*ing 7

如果您不关心元素的顺序,我推荐ListAssert.assertEquals使用junit-addons.

链接:http://junit-addons.sourceforge.net/

对于懒惰的Maven用户:

    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

  • 我同意.这个库很粗糙.为什么ListAssert.assertEquals()默认为无顺序? (11认同)
  • 注意:如果您不关心元素的顺序,则应使用Set或Collection,而不是List. (6认同)

Dhy*_*das 5

您可以在 junit 中使用assertEquals

import org.junit.Assert;   
import org.junit.Test;

    @Test
    public void test_array_pass()
    {
        List<String> actual = Arrays.asList("fee", "fi", "foe");
        List<String> expected = Arrays.asList("fee", "fi", "foe");
        Assert.assertEquals(actual,expected);
    }
Run Code Online (Sandbox Code Playgroud)

如果元素的顺序不同,则会返回错误。

如果您要断言模型对象列表,那么您应该覆盖特定模型中的 equals 方法。

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj != null && obj instanceof ModelName) {
            ModelName other = (ModelName) obj;
            return this.getItem().equals(other.getItem()) ;
        }
        return false;
    }
Run Code Online (Sandbox Code Playgroud)