I recently came across a piece of code that used a Stack
1. The Stack seems to inherit from Vector. The JavaDoc indicated (and so did my IDE, I think) that I should be using the Deque
2 interface instead. To be precise:
“A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class.”
Dequeue basically seems to be a specialized Queue
3, that supports element insertion and removal at both ends
4.
In order to get to grips with Deque, I decided to write some simple tests. These are JUnit Tests (version 4.12) and in one I used Hamcrest
5 and in the other I went for AssertJ
6.
Let's see what happens.
A simple compare
Hamcrest:
assertThat(actual, equalTo(testdata2));
AssertJ:
assertThat(actual).isEqualTo(testdata2);
Collections
Hamcrest:
assertThat(transmittedTestdata, hasSize(2));
AssertJ:
assertThat(transmittedTestdata).size().isEqualTo(2);
Null Values
Hamcrest:
assertThat(actual, not(nullValue()));
AssertJ:
assertThat(actual).isNotNull();
Exceptions
Hamcrest:
@Test(expected = NoSuchElementException.class)
public void testEmptyDequeueException()
{
Deque<Testdata> transmittedTestdata = new ConcurrentLinkedDeque<>();
Testdata pop = transmittedTestdata.pop();
}
AssertJ:
assertThatThrownBy(transmittedTestdata::pop).isInstanceOf(NoSuchElementException.class);
Imports
A comparison between the required imports of Hamcrest and Assertj is interesting:
Hamcrest:
import java.util.Deque;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedDeque;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasSize;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
AssertJ:
import java.util.Deque;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentLinkedDeque;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
Notes
- I really like the AssertJ fluent API. It feels more natural to me than the Hamcrest one.
- It is way easier to find the appropriate matchers in AssertJ. I get the full benefit of my IDE code completion.
- Adding the appropriate import is way easier. Using Hamcrest, I always get a choice of five different imports for the same matcher.
- I need fewer imports anyways.
So far, I like AssertJ a lot.
I need to work with AssertJ a lot more, to see some of the interesting stuff.
References
- [1] Java 7 JavaDoc - Stack
- https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html
- [2] Java 7 JavaDoc - Deque
- https://docs.oracle.com/javase/7/docs/api/java/util/Deque.html
- [3] Java 7 JavaDoc - Queue
- https://docs.oracle.com/javase/7/docs/api/java/util/Queue.html
- [4] Wikipedia - Double-ended queue
- https://en.wikipedia.org/wiki/Double-ended_queue
- [5] Hamcrest - Matchers that can be combined to create flexible expressions of intent
- http://hamcrest.org/
- [6] AssertJ - Quick start
- http://joel-costigliola.github.io/assertj/assertj-core-quick-start.html