Java 断言 Optional 有一定的价值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38954742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:46:14  来源:igfitidea点击:

Assert that Optional has certain value

javaunit-testingoptional

提问by Matthias Braun

I have a Java method that returns an Optional. I'd like to write an easy-to-read unit test for it that asserts that

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

  1. the returned Optional has a value (i.e., the Optional is not empty) and that

  2. the returned value is equal to an expected value.

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

  2. 返回值等于预期值。

Let's say my tested method is

假设我的测试方法是

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

采纳答案by Spotted

You can also use AssertJfor fluent assertions

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

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

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

回答by Matthias Braun

I use Hamcrest Optionalfor that:

我为此使用Hamcrest Optional

import static com.github.npathai.hamcrestopt.OptionalMatchers.hasValue;
import org.junit.Test;

public class MyUnitTests {

  @Test
  public void testThatOptionalHasValue(){
    String expectedValue = "actual value";
    assertThat(testedMethod(), hasValue(expectedValue));
  }
}

You can add Hamcrest Optional to your dependencies by including it in your build.gradle:

您可以通过将 Hamcrest Optional 添加到您的依赖项中build.gradle

dependencies {
  testCompile 'junit:junit:4.12'
  testCompile 'com.github.npathai:hamcrest-optional:1.0'
}

回答by mzq

Why don't you use isPresent()and get()?

你为什么不使用isPresent()get()

回答by Ben Green

The below approach uses the fact that you can specify a default return for an optional. So your test method could be something like this:

下面的方法使用了一个事实,即您可以为一个可选项指定一个默认返回值。所以你的测试方法可能是这样的:

@test
public void testThatOptionalHasValue() {
    String expectedValue = "actual value";
    String actualValue = Optional.ofNullable(testedMethod()).orElse("not " + expectedValue);
    assertEquals("The values are not the same", expectedValue, actualValue);
}

This guarentees that if your method returns null, then the result can not be the same as the expected value.

这保证如果您的方法返回 null,则结果不能与预期值相同。

回答by Stuart Marks

TL;DR the best overall approach was suggested by Ole V. V.:

TL;DR Ole VV 建议的最佳整体方法:

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

Other alternatives are discussed below.

下面讨论其他替代方案。

There are several different ways to do this, depending on your taste for clarity of test results vs. conciseness of test writing. For this answer I'll stick to "stock" Java 8 and JUnit 4 with no additional dependencies.

有几种不同的方法可以做到这一点,这取决于您对测试结果的清晰性与测试编写的简洁性的喜好。对于这个答案,我将坚持“库存”Java 8 和 JUnit 4,没有额外的依赖。

One way, as suggested in a comment by Ole V.V., is simply to write

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

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

This mostly works but if the Optional is empty, then get()will throw NoSuchElementException. This in turn causes JUnit to signal an error instead of a failure, which might not be what you want. It's also not very clear what's going on unless you already know that get()throws NSEE in this case.

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

An alternative is

另一种选择是

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

This also mostly works but it doesn't report the actual value if there's a mismatch, which might make debugging inconvenient.

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

Another alternative is

另一种选择是

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

This gives the right failures and reports the actual value when there's a mismatch, but it's not very explicit about why AssertionFailedErroris thrown. You might have to stare at it a while until you realize that AFE gets thrown when the Optional is empty.

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

Still another alternative is

还有一个选择是

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

but this is starting to get verbose.

但这开始变得冗长。

You could split this into two assertions,

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

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

but you had previously objected to this suggestionbecause of verbosity. This isn't really terribly verbose in my opinion, but it does have some cognitive overhead since there are two separate assertions, and it relies on the second only being checked if the first succeeds. This is not incorrect but it is a bit subtle.

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

Finally, if you're willing to create a bit of your own infrastructure, you could create a suitably-named subclass of AssertionFailedErrorand use it like this:

最后,如果您愿意创建一些自己的基础设施,您可以创建一个适当命名的子类AssertionFailedError并像这样使用它:

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

Finally, in another comment, Ole V. V. suggested

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

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

This works quite well, and in fact this might be the best of all.

这很有效,事实上这可能是最好的。