断言可选具有特定值

2022-08-31 22:23:24

我有一个返回可选的Java方法。我想为它写一个易于阅读的单元测试,断言

  1. 返回的 Optional 有一个值(即,Optional 不为空),并且

  2. 返回值等于预期值。

假设我测试的方法是

Optional<String> testedMethod(){
  return Optional.of("actual value");
}

答案 1

您还可以使用 AssertJ 进行流畅的断言

@Test
public void testThatOptionalIsNotEmpty() {
    assertThat(testedMethod()).isNotEmpty();
}

@Test
public void testThatOptionalHasValue() {
    assertThat(testedMethod()).hasValue("hello");
}

答案 2

TL;DR 最好的整体方法是 Ole V. V.

assertEquals(Optional.of("expected"), opt);

其他替代方案将在下面讨论。

有几种不同的方法可以做到这一点,这取决于您对测试结果清晰度的品味与测试写作的简洁性。对于这个答案,我将坚持使用“库存”Java 8和JUnit 4,没有其他依赖项。

正如Ole V.V.的评论所建议的那样,一种方法是简单地写

assertEquals("expected", opt.get());

这主要有效,但如果可选为空,则将抛出 .这反过来又会导致 JUnit 发出错误信号,而不是失败,这可能不是您想要的。也不是很清楚发生了什么,除非你已经知道在这种情况下抛出NSEE。get()NoSuchElementExceptionget()

另一种选择是

assertTrue(opt.isPresent() && "expected".equals(opt.get()));

这也主要有效,但如果存在不匹配,它不会报告实际值,这可能会使调试不方便。

另一种选择是

assertEquals("expected", opt.orElseThrow(AssertionFailedError::new));

这给出了正确的失败,并在存在不匹配时报告实际值,但对于抛出的原因并不是很明确。您可能需要盯着它看一会儿,直到您意识到AFE在可选为空时被抛出。AssertionFailedError

还有另一种选择是

assertEquals("expected", opt.orElseThrow(() -> new AssertionFailedError("empty")));

但这开始变得冗长。

你可以把它分成两个断言,

assertTrue(opt.isPresent());
assertEquals("expected", opt.get());

但是你以前因为冗长而反对这个建议。在我看来,这并不是非常冗长,但它确实有一些认知开销,因为有两个单独的断言,并且它依赖于第二个断言,只有在第一个成功时才被检查。这不是不正确的,但它有点微妙。

最后,如果您愿意创建一些自己的基础结构,则可以创建一个适当命名的子类,并按如下方式使用它:AssertionFailedError

assertEquals("expected", opt.orElseThrow(UnexpectedEmptyOptional::new));

最后,在另一条评论中,Ole V. V.建议

assertEquals(Optional.of("correct"), opt);

这工作得很好,实际上这可能是最好的。


推荐