Testing Optional Return Type

1. Introduction

In this article I will discuss how to assert an Optional. I have written a series of articles on Optional, which includes introduction, uses and abuses of Optional API. Optional is a class introduced in Java 8, which may or may not contain a non-null value. They should depict where a result is present or not. I will now provide a way to assert Optional return type.

2. Content

2.1. Optional.get()

This is one of the most simplistic way to test for Optional. But it is susceptible to throw NoSuchElementException if the Optional is empty.

assertEquals("expectedValue", optional.get()); 

java.util.NoSuchElementException: No value present
 at java.util.Optional.get(Optional.java:135)
 at com.justamonad.base.OptionalTest.test1(OptionalTest.java:17)

What we want is an AssertionError if the assert fail which will print out error in meaningful way.

2.2. isPresent() and get()

We can use a combination of isPresent() and get() so the Optional won’t throw NoSuchElementException. But regardless, this will be hard to debug if we don’t have expected value as the assert won’t give out a proper message. Don’t use a combination of isPresent() and get() method to extract out value from Optional. Read more here on How to use Optional?

assertTrue(optional.isPresent() 
				&& "expectedValue".equals(optional.get()));

java.lang.AssertionError
 at org.junit.Assert.fail(Assert.java:86)
 at org.junit.Assert.assertTrue(Assert.java:41)
 at org.junit.Assert.assertTrue(Assert.java:52)
 at com.justamonad.base.OptionalTest.test2(OptionalTest.java:22)

2.2. Use Optional.of(expected_value)

The better approach to test Optional would be to leverage the use of existing method equals(). The equality of Optional will be determined by Objects.equals(Object o1, Object o2). This way it would be better because Optional won’t throw NoSuchElementException and also AssertionError will less us know what went wrong.

Optional<String> optional = Optional.empty();
assertEquals(Optional.of("blah"), optional);

java.lang.AssertionError: expected:<Optional[blah]> but was:<Optional.empty>
 at org.junit.Assert.fail(Assert.java:88)
 at org.junit.Assert.failNotEquals(Assert.java:743)
 at org.junit.Assert.assertEquals(Assert.java:118)
 at org.junit.Assert.assertEquals(Assert.java:144)
 at com.justamonad.base.OptionalTest.test4(OptionalTest.java:33)

AssertionError, while passing wrong result in Optional.

Optional<String> optional = Optional.of("expectedValue")
assertEquals(Optional.of("blah"), optional); 

java.lang.AssertionError: expected:<Optional[blah]> but was:<Optional[expectedValue]>
 at org.junit.Assert.fail(Assert.java:88)
 at org.junit.Assert.failNotEquals(Assert.java:743)
 at org.junit.Assert.assertEquals(Assert.java:118)
 at org.junit.Assert.assertEquals(Assert.java:144)
 at com.justamonad.base.OptionalTest.test4(OptionalTest.java:33)

3. Conclusion

In this article, we discussed a few different ways to assert or test Optional. Using Optional of expected value is the superior way to test as it would save us from looking at nagging NoSuchElementException 🙂 and also the AssertionError will print out the required details to debug the test.

Leave a Reply

Your email address will not be published. Required fields are marked *