Name: java-hamcrest
Owner: Spotify
Description: Libraries that extend the Hamcrest matching library with useful matchers
Created: 2016-12-26 20:23:31.0
Updated: 2018-05-03 17:10:19.0
Pushed: 2017-12-12 17:37:26.0
Size: 118
Language: Java
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
This is a collection of libraries extending the Hamcrest matching library with useful matchers. We consider this library in beta but use it in many of our internal projects.
Each of these modules is published to Maven Central with the groupId of com.spotify
.
The list of modules available is:
Many applications at Spotify are very data heavy. They might be aggregation services that combine a lot of data structures into even more complicated data structures. And the basic data structures are usually complicated to begin with.
The POJO matcher library lets you describe the structure of a POJO in a fluent style and then match against that structure. It's optimized for very complicated objects with a lot of properties. When a mismatch occurs, the library tries to minimally describe the mismatch.
Example:
l List<User> users;
(Stream<User> userStream = sut.fetchAllUsers()) {
ers = userStream.collect(Collectors.toList());
rtThat(users, contains(
pojo(User.class)
.where("address", is(
pojo(Address.class)
.withProperty("street", is("Main Street"))
.withProperty("country", is("US"))
))
.where("product", is(
pojo(Product.class)
.withProperty("id", is(1))
.withProperty("name", is("premium"))
.withProperty("metadata", is("{\"foo\": [\"bar\", \"baz\"]}"))
.withProperty("creationDate", is(Timestamp.from(Instant.EPOCH)))
.withProperty("isTest", is(false))
))
Example output:
cted:
able containing [User {
dress(): is Address {
getStreet(): is "Main Street"
getCountry(): is "US"
oduct(): is Product {
getId(): is <1>
getName(): is "premium"
getMetadata(): is "{\"foo\": [\"bar\", \"baz\"]}"
getCreationDate(): is <1970-01-01 01:00:00.0>
getIsTest(): is <false>
0: User {
.
oduct(): Product {
...
getMetadata(): was "{\"foo\": \"bar\"}"
...
.
Similar to the POJO matchers, the JSON matchers let you describe a JSON structure and match against it.
The match can be on a String
or a jackson JsonNode
.
ou can match a String
ng jsonString = "{" +
\"foo\": 1," +
\"bar\": true," +
\"baz\": {" +
\"foo\": true" +
}" +
ou can match a Json String directly
rtThat("{}", isJsonStringMatching(jsonObject()));
r match a Jackson node
Node json = new ObjectMapper().readTree(jsonString);
rtThat(json, is(
jsonObject()
.where("foo", is(jsonInt(1)))
.where("bar", is(jsonBoolean(true)))
.where("baz", is(
jsonObject()
.where("foo", is(jsonNull()))))));
A failing test would look like:
cted:
oo": is a number node is <1>
ar": is a boolean node is <false>
az": is {
"foo": is a null node
.
az": {
...
"foo": was not a null node, but a boolean node
...
.
com.spotify:hamcrest-optional
provides matchers for the Java 8
Optional type so you don't have to unpack the Optional in your tests.
l Optional<String> response = methodUnderTest();
rtThat(response, is(optionalWithValue(equalTo("foo")));
l Optional<Collection<Foo>> col = anotherMethod();
rtThat(response, is(optionalWithValue(containsInAnyOrder(...))));
r if you only care that the Optional is non-empty:
rtThat(response, is(optionalWithValue()));
r if you expect an empty Optional:
rtThat(response, is(emptyOptional()));
Similar to the Optional matchers, the CompletionStage /
CompletableFuture matchers in com.spotify:hamcrest-future
allow
you to assert against the value or completion state of a
CompletionStage without having to unpack it in your test code or
handle the checked exceptions of Future.get()
(or using
Futures.getUnchecked(future)
).
There are four dimensions you can choose from when using Future matchers:
Future
vs Java 8's CompletableFuture
So there are a total of 16 methods you can call:
Future
matchersUse com.spotify.hamcrest.future.FutureMatchers
:
| | blocking | non-blocking | | ———– | ————————————— | ———— | | successful | futureWillCompleteWithValue[That]() | futureCompletedWithValue[That]() | | exceptional | futureWillCompleteWithException[That]() | futureCompletedWithException[That]() |
CompletableFuture
matchersUse com.spotify.hamcrest.future.CompletableFutureMatchers
:
| | blocking | non-blocking | | ———– | ————————————– | ———— | | successful | stageWillCompleteWithValue[That]() | stageCompletedWithValue[That]() | | exceptional | stageWillCompleteWithException[That]() | stageCompletedWithException[That]() |
Note that to test that a CompletionStage completed with a certain
value or exception use ..That(..)
.
letionStage<List<Foo>> f = someMethod();
rtThat(f, stageCompletedWithValueThat(contains(...));
letionStage<Foo> c = methodThatShouldFail();
rtThat(c, stageCompletedWithExceptionThat(isA(FooException.class)));
If you want the matcher to block until the CompletionStage is
completed, use stageWillCompleteWithValueThat(..)
:
arning: might block forever if the stage never completes!
letionStage<List<Foo>> f = someMethod();
rtThat(f, stageWillCompleteWithValueThat(is(equalTo(...)));
Be careful when using this matcher as it might block forever if the stage never completes! Consider restructuring your tests so that the completions returned from the method/class being tested are immediately completed (e.g. using MoreExecutors.directExecutor, etc).
Any platform that has the following
This plugin is uploaded to Maven Central via the Maven release plugin. You'll need
credentials for Spotify's Sonatype account in your ~/.m2/settings.xml
as well as a GPG key to
sign the artifacts.
-Dgpg.keyname=<KEY-ID> release:prepare release:perform
This project adheres to the Open Code of Conduct. By participating, you are expected to honor this code.