如何JUnit测试两个List<E>以相同的顺序包含相同的元素?

2022-08-31 11:59:51

上下文

我正在为该类编写一个简单的JUnit测试。MyObject

可以从静态工厂方法创建 A,该方法采用 String 的 varargs。MyObject

MyObject.ofComponents("Uno", "Dos", "Tres");

在 存在 期间的任何时间,客户端都可以通过该方法检查以 List<E> 的形式创建它的参数。MyObject.getComponents()

myObject.ofComponents(); // -> List<String>: { "Uno", "Dos", "Tres" }

换句话说,a 既记住又公开了使其存在的参数列表。有关此合同的更多详细信息:MyObject

  • 的顺序将与为创建对象选择的顺序相同getComponents
  • 允许并按顺序保留重复的后续字符串组件
  • 上的行为未定义(其他代码保证无法到达工厂)nullnull
  • 在对象实例化后,无法更改组件列表

我正在编写一个简单的测试,该测试从字符串列表中创建一个并检查它是否可以通过返回相同的列表。我立即这样做,但这应该在现实代码路径中的远处发生MyObject.getComponents()

法典

这是我的尝试:


List<String> argumentComponents = Lists.newArrayList("One", "Two", "Three");
List<String> returnedComponents =
    MyObject.ofComponents(
        argumentComponents.toArray(new String[argumentComponents.size()]))
        .getComponents();
assertTrue(Iterables.elementsEqual(argumentComponents, returnedComponents));

问题

  • Google Guava是比较这两个列表的最佳方式吗?前提是我在构建路径中有库?这是我一直在苦恼的事情;我是否应该使用这个帮助器方法,它遍历了一个迭代<E>...检查大小,然后迭代运行.equals()...或Internet搜索建议的任何其他方法?比较单元测试列表的规范方法是什么?Iterables.elementsEqual()

我很乐意获得的可选见解

  • 方法测试设计合理吗?我不是JUnit的专家!
  • List<E> 转换为 E 的 varargs 的最佳方法是什么?.toArray()

答案 1

为什么不直接使用?List#equals

assertEquals(argumentComponents, imapPathComponents);

列表的合同#等于

如果两个列表以相同的顺序包含相同的元素,则将其定义为相等。


答案 2

我更喜欢使用Hamcrest,因为它在发生故障时提供了更好的输出。

Assert.assertThat(listUnderTest, 
       IsIterableContainingInOrder.contains(expectedList.toArray()));

而不是报告

expected true, got false

它将报告

expected List containing "1, 2, 3, ..." got list containing "4, 6, 2, ..."

IsIterableContainingInOrder.contain

汉克雷斯特

根据Javadoc的说法:

为 Iterables 创建一个匹配器,当对已检查的 Iterable 的单次传递生成一系列项时,该匹配器将匹配该匹配项,每个项在逻辑上等于指定项中的相应项。对于正匹配,已检查的可迭代对象的长度必须与指定项的数量相同

因此,必须具有相同数量的元素,并且每个元素必须按顺序匹配预期值。listUnderTest


推荐