簡體   English   中英

斷言 Optional 有一定的價值

[英]Assert that Optional has certain value

我有一個返回Optional的Java方法。 我想為它編寫一個易於閱讀的單元測試,斷言

  1. 返回的 Optional 有一個值(即 Optional 不為空)並且

  2. 返回值等於預期值。

假設我的測試方法是

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

您也可以使用AssertJ進行流暢的斷言

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

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

TL; DR是Ole VV建議的最佳整體方法:

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

下面討論其他替代方案。

有幾種不同的方法可以做到這一點,這取決於您對測試結果清晰度的要求與測試寫作的簡潔性。 對於這個答案,我將堅持“庫存”Java 8和JUnit 4,沒有其他依賴。

正如Ole VV評論中所建議的那樣,一種方法就是寫作

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

這通常有效但如果Optional為空,則get()將拋出NoSuchElementException 這反過來導致JUnit發出錯誤信號而不是失敗,這可能不是你想要的。 除非你已經知道get()在這種情況下拋出NSEE,否則還不是很清楚會發生什么。

另一種選擇是

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

這也很有效,但如果不匹配則不會報告實際值,這可能會使調試變得不方便。

另一種選擇是

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

這會給出正確的失敗並在出現不匹配時報告實際值,但是為什么拋出AssertionFailedError並不是很清楚。 您可能需要盯着它一段時間,直到您意識到當Optional為空時AFE被拋出。

另一種選擇是

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

但這開始變得冗長。

你可以把它分成兩個斷言,

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

但是你之前因為冗長而反對這個建議 在我看來,這並不是非常非常冗長,但它確實有一些認知開銷,因為有兩個單獨的斷言,並且它依賴於第二個僅在第一個成功時被檢查。 這不是不正確的,但有點微妙。

最后,如果您願意創建一些自己的基礎結構,可以創建一個適當命名的AssertionFailedError子類,並像這樣使用它:

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

最后,在另一條評論中,Ole VV建議

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

這很有效,事實上這可能是最好的。

我使用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));
  }
}

您可以將Hamcrest Optional添加到您的依賴項中,方法是將它包含在build.gradle

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

以下方法使用您可以為可選項指定默認返回的事實。 所以你的測試方法可能是這樣的:

@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);
}

這保證如果您的方法返回null,則結果不能與期望值相同。

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

我更喜歡在斷言之前將 .orElse(null) 應用於返回的 Optional 。

方法 assertEquals 可以與包含預期值的 Optional 一起使用(或 assertThat(result).isEqualTo(expected) 在使用 FEST 斷言時)。

但是使用 .orElse 的好處是結果具有正確的類型,並且如果該方法不是可選的,則允許執行您可能想要執行的所有檢查:

  • == 運算符(或使用 FEST 時的 isSame 方法)
  • compareTo 和使用 compareTo 的方法
  • 在字符串的情況下,startsWith、endsWith、contains、長度
  • ...

使用預期值的 Optional 不允許所有這些事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM