Skip to content

Commit e44c1d7

Browse files
committed
Optional matchers
1 parent 6bb90de commit e44c1d7

File tree

4 files changed

+256
-0
lines changed

4 files changed

+256
-0
lines changed

hamcrest/src/main/java/org/hamcrest/Matchers.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import org.hamcrest.collection.ArrayMatching;
44
import org.hamcrest.core.IsIterableContaining;
55
import org.hamcrest.core.StringRegularExpression;
6+
import org.hamcrest.optional.OptionalEmpty;
7+
import org.hamcrest.optional.OptionalWithValue;
68
import org.hamcrest.text.IsEqualCompressingWhiteSpace;
79

10+
import java.util.Optional;
811
import java.util.regex.Pattern;
912

1013
/**
@@ -2184,4 +2187,45 @@ public static org.hamcrest.Matcher<org.w3c.dom.Node> hasXPath(java.lang.String x
21842187
return org.hamcrest.xml.HasXPath.hasXPath(xPath, namespaceContext);
21852188
}
21862189

2190+
/**
2191+
* Matcher that expects empty {@link Optional}.
2192+
*
2193+
* @param <T> type of optional value
2194+
* @return The matcher.
2195+
*/
2196+
public static <T> Matcher<Optional<T>> emptyOptional() {
2197+
return OptionalEmpty.emptyOptional();
2198+
}
2199+
2200+
/**
2201+
* Matcher for {@link Optional} that expects that value is present.
2202+
*
2203+
* @param <T> type of optional value
2204+
* @return The matcher.
2205+
*/
2206+
public static <T> Matcher<Optional<T>> optionalWithValue() {
2207+
return OptionalWithValue.optionalWithValue();
2208+
}
2209+
2210+
/**
2211+
* Matcher for {@link Optional} that expects that value is present and is equal to <code>value</code>
2212+
*
2213+
* @param <T> type of optional value
2214+
* @param value to validate present optional value
2215+
* @return The matcher.
2216+
*/
2217+
public static <T> Matcher<Optional<T>> optionalWithValue(T value) {
2218+
return OptionalWithValue.optionalWithValue(value);
2219+
}
2220+
2221+
/**
2222+
* Matcher for {@link Optional} that expects that value is present and matches <code>matcher</code>
2223+
*
2224+
* @param <T> type of optional value
2225+
* @param matcher matcher to validate present optional value
2226+
* @return The matcher.
2227+
*/
2228+
public static <T> Matcher<Optional<T>> optionalWithValue(Matcher<? super T> matcher) {
2229+
return OptionalWithValue.optionalWithValue(matcher);
2230+
}
21872231
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package org.hamcrest.optional;
2+
3+
import org.hamcrest.Description;
4+
import org.hamcrest.Matcher;
5+
import org.hamcrest.TypeSafeDiagnosingMatcher;
6+
7+
import java.util.Optional;
8+
9+
/**
10+
* Matcher that expects empty {@link Optional}.
11+
12+
* @param <T> type of {@link Optional} value
13+
*/
14+
public class OptionalEmpty<T> extends TypeSafeDiagnosingMatcher<Optional<T>> {
15+
16+
/**
17+
* Matcher that expects empty {@link Optional}.
18+
*
19+
* @param <T> type of optional value
20+
* @return The matcher.
21+
*/
22+
public static <T> Matcher<Optional<T>> emptyOptional() {
23+
return new OptionalEmpty<>();
24+
}
25+
26+
@Override
27+
protected boolean matchesSafely(Optional<T> value, Description mismatchDescription) {
28+
mismatchDescription.appendText("is " + value);
29+
return !value.isPresent();
30+
}
31+
32+
@Override
33+
public void describeTo(Description description) {
34+
description.appendText("empty");
35+
}
36+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.hamcrest.optional;
2+
3+
import org.hamcrest.Description;
4+
import org.hamcrest.Matcher;
5+
import org.hamcrest.TypeSafeDiagnosingMatcher;
6+
import org.hamcrest.core.IsAnything;
7+
8+
import java.util.Optional;
9+
10+
import static org.hamcrest.core.IsEqual.equalTo;
11+
12+
/**
13+
* Matcher for {@link Optional} that expects that value is present.
14+
*
15+
* @param <T> type of {@link Optional} value
16+
*/
17+
public class OptionalWithValue<T> extends TypeSafeDiagnosingMatcher<Optional<T>> {
18+
19+
private final Matcher<? super T> matcher;
20+
21+
/**
22+
* Constructor.
23+
*
24+
* @param matcher matcher to validate present optional value
25+
*/
26+
public OptionalWithValue(Matcher<? super T> matcher) {
27+
this.matcher = matcher;
28+
}
29+
30+
/**
31+
* Matcher for {@link Optional} that expects that value is present.
32+
*
33+
* @param <T> type of optional value
34+
* @return The matcher.
35+
*/
36+
public static <T> Matcher<Optional<T>> optionalWithValue() {
37+
return new OptionalWithValue<>(IsAnything.anything("any"));
38+
}
39+
40+
/**
41+
* Matcher for {@link Optional} that expects that value is present and is equal to <code>value</code>
42+
*
43+
* @param <T> type of optional value
44+
* @param value to validate present optional value
45+
* @return The matcher.
46+
*/
47+
public static <T> Matcher<Optional<T>> optionalWithValue(T value) {
48+
return new OptionalWithValue<>(equalTo(value));
49+
}
50+
51+
/**
52+
* Matcher for {@link Optional} that expects that value is present and matches <code>matcher</code>
53+
*
54+
* @param <T> type of optional value
55+
* @param matcher matcher to validate present optional value
56+
* @return The matcher.
57+
*/
58+
public static <T> Matcher<Optional<T>> optionalWithValue(Matcher<? super T> matcher) {
59+
return new OptionalWithValue<>(matcher);
60+
}
61+
62+
@Override
63+
protected boolean matchesSafely(Optional<T> value, Description mismatchDescription) {
64+
mismatchDescription.appendText("is " + value);
65+
return value.isPresent() && matcher.matches(value.get());
66+
}
67+
68+
@Override
69+
public void describeTo(Description description) {
70+
description.appendText("present and matches ")
71+
.appendDescriptionOf(matcher);
72+
}
73+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package org.hamcrest.optional;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.equalTo;
5+
import static org.hamcrest.Matchers.is;
6+
import static org.hamcrest.Matchers.not;
7+
import static org.hamcrest.optional.OptionalEmpty.emptyOptional;
8+
import static org.hamcrest.optional.OptionalWithValue.optionalWithValue;
9+
import static org.junit.Assert.assertEquals;
10+
import static org.junit.Assert.assertThrows;
11+
12+
import java.util.Optional;
13+
14+
import org.junit.Test;
15+
16+
public class OptionalMatchersTest {
17+
18+
@Test
19+
public void checkEmptyOptional() {
20+
assertThat(Optional.empty(), is(emptyOptional()));
21+
assertThat(Optional.of(1), not(emptyOptional()));
22+
}
23+
24+
@Test
25+
public void checkEmptyOptionalFailure() {
26+
AssertionError failure = assertThrows(AssertionError.class, () -> {
27+
assertThat(Optional.of(1), emptyOptional());
28+
});
29+
assertEquals("\n" +
30+
"Expected: empty\n" +
31+
" but: is Optional[1]", failure.getMessage());
32+
}
33+
34+
@Test
35+
public void checkEmptyOptionalIsFailure() {
36+
AssertionError failure = assertThrows(AssertionError.class, () -> {
37+
assertThat(Optional.of(1), is(emptyOptional()));
38+
});
39+
assertEquals("\n" +
40+
"Expected: is empty\n" +
41+
" but: is Optional[1]", failure.getMessage());
42+
}
43+
44+
@Test
45+
public void checkEmptyOptionalIsNotFailure() {
46+
AssertionError failure = assertThrows(AssertionError.class, () -> {
47+
assertThat(Optional.empty(), is(not(emptyOptional())));
48+
});
49+
assertEquals("\n" +
50+
"Expected: is not empty\n" +
51+
" but: was <Optional.empty>", failure.getMessage());
52+
}
53+
54+
@Test
55+
public void checkWithValue() {
56+
assertThat(Optional.empty(), not(optionalWithValue()));
57+
assertThat(Optional.of(1), is(optionalWithValue()));
58+
}
59+
60+
@Test
61+
public void checkWithMatchingValue() {
62+
assertThat(Optional.empty(), not(optionalWithValue(equalTo(1))));
63+
assertThat(Optional.of(1), is(optionalWithValue(equalTo(1))));
64+
assertThat(Optional.of(1), not(optionalWithValue(equalTo(1L))));
65+
}
66+
67+
@Test
68+
public void checkWithLiteralValue() {
69+
assertThat(Optional.empty(), not(optionalWithValue(1)));
70+
assertThat(Optional.of(1), is(optionalWithValue(1)));
71+
assertThat(Optional.of(1), not(optionalWithValue(1L)));
72+
}
73+
74+
@Test
75+
public void checkWithValueFailure() {
76+
AssertionError failure = assertThrows(AssertionError.class, () -> {
77+
assertThat(Optional.empty(), is(optionalWithValue()));
78+
});
79+
assertEquals("\n" +
80+
"Expected: is present and matches any\n" +
81+
" but: is Optional.empty", failure.getMessage());
82+
}
83+
84+
@Test
85+
public void checkWithMatchingValueFailure() {
86+
AssertionError failure = assertThrows(AssertionError.class, () -> {
87+
assertThat(Optional.empty(), is(optionalWithValue(equalTo(1))));
88+
});
89+
assertEquals("\n" +
90+
"Expected: is present and matches <1>\n" +
91+
" but: is Optional.empty", failure.getMessage());
92+
}
93+
94+
@Test
95+
public void checkWithLiteralValueFailure() {
96+
AssertionError failure = assertThrows(AssertionError.class, () -> {
97+
assertThat(Optional.of("text"), is(optionalWithValue("Hello, world")));
98+
});
99+
assertEquals("\n" +
100+
"Expected: is present and matches \"Hello, world\"\n" +
101+
" but: is Optional[text]", failure.getMessage());
102+
}
103+
}

0 commit comments

Comments
 (0)