2016-08-15 47 views
11

我有一個返回Optional的Java方法。 我想編寫一個易於閱讀的單元測試它斷言斷言可選具有一定的值

  1. 返回可選有一個值(即擇不爲空),並且

  2. 的返回值等於預期值。

比方說,我的測試方法是

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

我只是簡單地使用'assertEquals(「actual value」,testedMethod()。get());'如果可選項爲空,它將會失敗,這足以讓你的單元測試失敗,所以你真的不需要更多。 –

回答

12

您還可以使用AssertJ爲流暢的斷言

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

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

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

您可以通過它在你的build.gradle添加Hamcrest可選到你的依賴:

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

爲什麼不使用isPresent()get()

+0

這是兩個斷言,並導致一個非常詳細的單元測試。我在找東西。 –

1

下面的方法使用的事實,你可以指定一個可選的一個默認的回報。所以你的測試方法可能是這樣的:

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

這guarentees,如果你的方法返回null,則結果不能是相同的預期值。

12

有幾種不同的方法可以做到這一點,這取決於您的口味,以便測試結果的清晰度和測試寫作的簡潔性。對於這個答案,我將堅持「股票」Java 8和JUnit 4沒有額外的依賴。

的一種方式,如在comment by Ole V.V.建議,僅僅是寫

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

這主要工作,但如果可選爲空,則get()將拋出NoSuchElementException。這反過來導致JUnit發出錯誤信號而不是錯誤信號,這可能不是您想要的。這也不是很清楚,除非你已經知道get()在這種情況下拋出NSEE。

另一種方法是

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

這也主要是作品,但如果有一個不匹配,這可能使調試不方便它不報告的實際值。

另一種方法是

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

這給正確的失敗和報告的實際價值時,有一個不匹配,但它不是關於爲什麼AssertionFailedError被拋出非常明確的。您可能不得不盯住它,直到您意識到AFE在Optional爲空時被拋出。

還有另一種選擇是

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

但這開始變得冗長。

你可以分裂成兩個斷言此,

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

,但你此前曾反對this suggestion因爲冗長的。這在我看來並不是非常詳細,但是它確實存在一些認知開銷,因爲有兩個單獨的斷言,並且只有在第一次成功時才依靠第二次檢查。這不是不正確的,但它有點微妙。

最後,如果你願意創建一個有點自己的基礎設施,您可以創建的AssertionFailedError適當命名的子類,並使用它像這樣:

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

UPDATE在評論,奧VV建議

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

這工作得很好,實際上這可能是最好的。

+0

如果您接受'null'作爲缺少值的另一個常規表示形式,則還有'assertEquals(「correct」,opt.orElse(null));'。這不是我個人的偏好,但它應該是你的,繼續。 –

+10

再想一想,有'assertEquals(Option al.of(「corre ct」),opt);''也是。這很簡單,雖然我花了一段時間想寫它,但可以閱讀,不是嗎?我也希望它在失敗的時候給出好的,明確的信息,在'opt'存在錯誤值和空白的情況下。 –

+0

@ OleV.V。好建議! –