Junit - 断言列表包含

10
我正在创建一个包含几个元素的列表(ArrayList)。 我想确保它包含我添加的元素。 现在,这只有在一些情况下才能正常工作,因为顺序会改变:
@Test
public void testThreeReporters(){
    ClientConfig myConfig = new ClientConfigFactory().getConfig().withMetricsReporters(new HashSet<>(Arrays.asList(ClientConfig.MetricsReporterType.LOG, ClientConfig.MetricsReporterType.GRAPHITE, ClientConfig.MetricsReporterType.CLOUD_WATCH)));
    List<ScheduledReporter> reporters = MetricsFactory.configureMetricsReporters(MetricsFactory.createMetricsClient(),myConfig);
    assertEquals(3, reporters.size());

    assertTrue(reporters.get(2) instanceof Slf4jReporter);
    assertTrue(reporters.get(1) instanceof GraphiteReporter);
    assertTrue(reporters.get(0) instanceof CloudWatchReporter);
}

我想使用“contains”,以避免受到顺序的影响。 我尝试了以下代码:

 assertTrue(Arrays.asList(reporters).contains((Arrays.asList(ClientConfig.MetricsReporterType.LOG, ClientConfig.MetricsReporterType.GRAPHITE, ClientConfig.MetricsReporterType.CLOUD_WATCH))));

还有其他组合方式,但是它不能正常工作。


2
“它不起作用” - 您肯定已经在这里待了足够长的时间,知道这还不够好... - Joe C
这真的取决于“MetricsFactory.configureMetricsReporters”的实现方式。如果它按顺序将元素添加到列表中,那么您的问题就很简单,您只需要在myConfig中添加/强制排序即可。您可以使用TreeSet来实现 https://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html - maneet
4个回答

18
assertEquals(3, reporters.size());
assertTrue(reporters.stream().anyMatch(e -> e instanceof Slf4jReporter));
assertTrue(reporters.stream().anyMatch(e -> e instanceof GraphiteReporter));
assertTrue(reporters.stream().anyMatch(e -> e instanceof CloudWatchReporter));

看起来不错,但如果我没记错的话 - 我不能在 Java 7 中使用 lambda 表达式。 - user2880391
然后使用Java 8,或编写一个方法,如果列表中的元素是给定类的实例,则返回true,并调用该方法,而不是使用内置的流方法。或者使用Guava,它具有这样的内置实用程序方法。或者像Janos建议的那样使用AssertJ。 - JB Nizet

4

使用纯JUnit,没有简单的方法来完成这个任务。

您可以开发一个辅助方法,使用@JBNizet在他的答案中演示的技术,使其变得更加容易。

或者您可以使用其他测试库来帮助完成此任务。例如,使用AssertJ,您可以这样做:

import static org.assertj.core.api.Assertions.assertThat;

// ...

assertThat(reporters).extracting("class").contains(
    Slf4jReporter.class,
    GraphiteReporter.class,
    CloudWatchReporter.class
);

如果您使用Maven,可以像这样添加assertj依赖项:
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.4.1</version>
</dependency>

在 'reporters' 上获取 'Cannot resolve method 'assertThat(java.util.List<...>)'。 - user2880391
就像对于assertTrue()方法一样,您需要静态导入该方法。如文档所述:http://joel-costigliola.github.io/assertj/index.html。 - JB Nizet
@user2880391,请确保你已经从assertj中导入了assertThat,而不是从junit中导入:import static org.assertj.core.api.Assertions.assertThat; - janos
很好。非常感谢。 - user2880391

0
你可以使用布尔变量并遍历数组。如果找到了想要的元素,将布尔变量设置为 true。在迭代完成后,断言变量为 true。

0
问题在于您试图检查reporters列表是否包含一个列表,但实际上它不包含列表,因为您已经指定它包含ScheduledReporter的实例。我没有使用过这些类,所以无法提供更优雅的解决方案,但以下代码应该可以工作:
@Test
public void testThreeReporters() {
    ClientConfig myConfig = new ClientConfigFactory().getConfig().withMetricsReporters(new HashSet<>(Arrays.asList(ClientConfig.MetricsReporterType.LOG, ClientConfig.MetricsReporterType.GRAPHITE, ClientConfig.MetricsReporterType.CLOUD_WATCH)));
    List<ScheduledReporter> reporters = MetricsFactory.configureMetricsReporters(MetricsFactory.createMetricsClient(),myConfig);
    assertEquals(3, reporters.size());

    assertTrue("No Slf4jReporter was found", containsReporter(reporters, Slf4jReporter.class));
    assertTrue("No GraphiteReporter was found", containsReporter(reportera, GraphiteReporter.class));
    assertTrue("No CloudWatchReporter was found", containsReporter(reporters, CloudWatchReporter.class));
}

/**
 * @return {@code true} if {@code reporters} contains an object of type
 *         {@code expectedClass}, otherwise {@code false}.
 */
private boolean containsReporter(List<ScheduledReporter> reporters, Class expectedClass) {
    for (ScheduledReporter reporter : reporters) {
        if (expectedClass.isInstance(reporter)) {
            return true;
        }
    }
    return false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接