Skip to content

Commit 6ffcf36

Browse files
author
smgfreeman
committed
Merged in Neil's mismatch implementation.
1 parent 9632e7e commit 6ffcf36

25 files changed

Lines changed: 366 additions & 90 deletions

File tree

hamcrest-core/src/main/java/org/hamcrest/BaseMatcher.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ public final void _dont_implement_Matcher___instead_extend_BaseMatcher_() {
1616
// See Matcher interface for an explanation of this method.
1717
}
1818

19+
public void describeMismatch(Object item, Description description) {
20+
description.appendText("was ").appendValue(item);
21+
}
22+
1923
@Override
2024
public String toString() {
2125
return StringDescription.toString(this);

hamcrest-core/src/main/java/org/hamcrest/Description.java

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,26 @@
77
* @see Matcher#describeTo(Description)
88
*/
99
public interface Description {
10-
10+
/**
11+
* A description that consumes input but does nothing.
12+
*/
13+
static final Description NONE = new NullDescription();
14+
1115
/**
1216
* Appends some plain text to the description.
1317
*/
1418
Description appendText(String text);
15-
19+
1620
/**
1721
* Appends the description of a {@link SelfDescribing} value to this description.
1822
*/
1923
Description appendDescriptionOf(SelfDescribing value);
20-
24+
2125
/**
2226
* Appends an arbitary value to the description.
2327
*/
2428
Description appendValue(Object value);
25-
29+
2630
/**
2731
* Appends a list of values to the description.
2832
*/
@@ -34,11 +38,46 @@ <T> Description appendValueList(String start, String separator, String end,
3438
*/
3539
<T> Description appendValueList(String start, String separator, String end,
3640
Iterable<T> values);
37-
38-
/**
41+
42+
/**
3943
* Appends a list of {@link org.hamcrest.SelfDescribing} objects
40-
* to the description.
44+
* to the description.
4145
*/
42-
Description appendList(String start, String separator, String end,
46+
Description appendList(String start, String separator, String end,
4347
Iterable<? extends SelfDescribing> values);
48+
49+
50+
public static final class NullDescription implements Description {
51+
public Description appendDescriptionOf(SelfDescribing value) {
52+
return this;
53+
}
54+
55+
public Description appendList(String start, String separator,
56+
String end, Iterable<? extends SelfDescribing> values) {
57+
return this;
58+
}
59+
60+
public Description appendText(String text) {
61+
return this;
62+
}
63+
64+
public Description appendValue(Object value) {
65+
return this;
66+
}
67+
68+
public <T> Description appendValueList(String start, String separator,
69+
String end, T... values) {
70+
return this;
71+
}
72+
73+
public <T> Description appendValueList(String start, String separator,
74+
String end, Iterable<T> values) {
75+
return this;
76+
}
77+
78+
@Override
79+
public String toString() {
80+
return "";
81+
}
82+
}
4483
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.hamcrest;
2+
3+
/**
4+
* TODO(ngd): Document.
5+
*
6+
* @param <T>
7+
*/
8+
public abstract class DiagnosingMatcher<T> extends BaseMatcher<T> {
9+
10+
public final boolean matches(Object item) {
11+
return matches(item, Description.NONE);
12+
}
13+
14+
@Override
15+
public final void describeMismatch(Object item, Description mismatchDescription) {
16+
matches(item, mismatchDescription);
17+
}
18+
19+
protected abstract boolean matches(Object item, Description mismatchDescription);
20+
}

hamcrest-core/src/main/java/org/hamcrest/Matcher.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
* @see CoreMatchers
1818
* @see BaseMatcher
1919
*/
20-
@SuppressWarnings({"unused"})
2120
public interface Matcher<T> extends SelfDescribing {
2221

2322
/**
@@ -34,15 +33,28 @@ public interface Matcher<T> extends SelfDescribing {
3433
* @see BaseMatcher
3534
*/
3635
boolean matches(Object item);
36+
37+
/**
38+
* Generate a description of why the matcher has not accepted the item.
39+
* The description will be part of a larger description of why a matching
40+
* failed, so it should be concise.
41+
* This method assumes that <code>matches(item)</code> is false, but
42+
* will not check this.
43+
*
44+
* @param item The item that the Matcher has rejected.
45+
* @param mismatchDescription
46+
* The description to be built or appended to.
47+
*/
48+
void describeMismatch(Object item, Description mismatchDescription);
3749

3850
/**
3951
* This method simply acts a friendly reminder not to implement Matcher directly and
4052
* instead extend BaseMatcher. It's easy to ignore JavaDoc, but a bit harder to ignore
4153
* compile errors .
42-
*
54+
*
4355
* @see Matcher for reasons why.
4456
* @see BaseMatcher
45-
* @deprecated to make
57+
* @deprecated to make
4658
*/
4759
@Deprecated
4860
void _dont_implement_Matcher___instead_extend_BaseMatcher_();

hamcrest-core/src/main/java/org/hamcrest/StringDescription.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public static String asString(SelfDescribing selfDescribing) {
3535
return toString(selfDescribing);
3636
}
3737

38+
@Override
3839
protected void append(String str) {
3940
try {
4041
out.append(str);
@@ -43,6 +44,7 @@ protected void append(String str) {
4344
}
4445
}
4546

47+
@Override
4648
protected void append(char c) {
4749
try {
4850
out.append(c);
@@ -54,6 +56,7 @@ protected void append(char c) {
5456
/**
5557
* Returns the description as a string.
5658
*/
59+
@Override
5760
public String toString() {
5861
return out.toString();
5962
}

hamcrest-core/src/main/java/org/hamcrest/core/AllOf.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,36 @@
55
import java.util.List;
66

77
import org.hamcrest.Description;
8+
import org.hamcrest.DiagnosingMatcher;
89
import org.hamcrest.Factory;
910
import org.hamcrest.Matcher;
1011

1112
/**
1213
* Calculates the logical conjunction of multiple matchers. Evaluation is shortcut, so
1314
* subsequent matchers are not called if an earlier matcher returns <code>false</code>.
1415
*/
15-
public class AllOf<T> extends ShortcutCombination<T> {
16+
public class AllOf<T> extends DiagnosingMatcher<T> {
17+
18+
private final Iterable<Matcher<? super T>> matchers;
1619

1720
public AllOf(Iterable<Matcher<? super T>> matchers) {
18-
super(matchers);
21+
this.matchers = matchers;
1922
}
2023

2124
@Override
22-
public boolean matches(Object o) {
23-
return matches(o, false);
25+
protected boolean matches(Object o, Description mismatchDescription) {
26+
for (Matcher<? super T> matcher : matchers) {
27+
if (!matcher.matches(o)) {
28+
mismatchDescription.appendDescriptionOf(matcher).appendText(" ");
29+
matcher.describeMismatch(o, mismatchDescription);
30+
return false;
31+
}
32+
}
33+
return true;
2434
}
2535

26-
@Override
2736
public void describeTo(Description description) {
28-
describeTo(description, "and");
37+
description.appendList("(", " " + "and" + " ", ")", matchers);
2938
}
3039

3140
/**

hamcrest-core/src/main/java/org/hamcrest/core/Is.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package org.hamcrest.core;
22

3-
import static org.hamcrest.core.IsInstanceOf.instanceOf;
43
import static org.hamcrest.core.IsEqual.equalTo;
5-
import org.hamcrest.Factory;
6-
import org.hamcrest.Matcher;
4+
import static org.hamcrest.core.IsInstanceOf.instanceOf;
5+
76
import org.hamcrest.BaseMatcher;
87
import org.hamcrest.Description;
8+
import org.hamcrest.Factory;
9+
import org.hamcrest.Matcher;
910

1011
/**
1112
* Decorates another Matcher, retaining the behavior but allowing tests
@@ -28,7 +29,13 @@ public boolean matches(Object arg) {
2829
public void describeTo(Description description) {
2930
description.appendText("is ").appendDescriptionOf(matcher);
3031
}
31-
32+
33+
@Override
34+
public void describeMismatch(Object item, Description mismatchDescription) {
35+
// TODO(ngd): unit tests....
36+
matcher.describeMismatch(item, mismatchDescription);
37+
}
38+
3239
/**
3340
* Decorates another Matcher, retaining the behavior but allowing tests
3441
* to be slightly more expressive.

hamcrest-core/src/main/java/org/hamcrest/core/IsAnything.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,22 @@
1313
*/
1414
public class IsAnything<T> extends BaseMatcher<T> {
1515

16-
private final String description;
16+
private final String message;
1717

1818
public IsAnything() {
1919
this("ANYTHING");
2020
}
2121

22-
public IsAnything(String description) {
23-
this.description = description;
22+
public IsAnything(String message) {
23+
this.message = message;
2424
}
2525

2626
public boolean matches(Object o) {
2727
return true;
2828
}
2929

3030
public void describeTo(Description description) {
31-
description.appendText(this.description);
31+
description.appendText(message);
3232
}
3333

3434
/**

hamcrest-examples/src/main/java/org/hamcrest/examples/junit4/ExampleWithAssertThat.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
import static org.hamcrest.Matchers.is;
66
import static org.hamcrest.Matchers.not;
77

8+
import org.hamcrest.Description;
9+
import org.hamcrest.Matcher;
10+
import org.hamcrest.TypeSafeMatcher;
811
import org.junit.Test;
912

1013
/**
@@ -28,5 +31,38 @@ public void usingAssertThat() {
2831
public static junit.framework.Test suite() {
2932
return new junit.framework.JUnit4TestAdapter(ExampleWithAssertThat.class);
3033
}
34+
35+
public static class ComplicatedClass {
36+
private int firstNumber = 23;
37+
private int secondNumber = 45;
38+
private String someText = "This is useful text";
39+
40+
public String whichOne(boolean first) {
41+
return someText + (first ? firstNumber : secondNumber);
42+
}
43+
}
44+
45+
@Test
46+
public void showMismatch() {
47+
ComplicatedClass complicated = new ComplicatedClass();
48+
49+
assertThat(complicated, shouldBe("the wrong thing"));
50+
}
51+
52+
private Matcher<ComplicatedClass> shouldBe(String string) {
53+
return new TypeSafeMatcher<ComplicatedClass>() {
54+
55+
public void describeTo(Description description) {
56+
// TODO Auto-generated method stub
57+
58+
}
59+
60+
@Override
61+
public boolean matchesSafely(ComplicatedClass item) {
62+
// TODO Auto-generated method stub
63+
return false;
64+
}
65+
};
66+
}
3167

3268
}

hamcrest-integration/src/main/java/org/hamcrest/MatcherAssert.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ public static <T> void assertThat(String reason, T actual, Matcher<? super T> ma
1616
.appendDescriptionOf(matcher)
1717
.appendText("\n got: ")
1818
.appendValue(actual)
19-
.appendText("\n");
19+
.appendText("\nmismatch: ");
20+
matcher.describeMismatch(actual, description);
2021

2122
throw new AssertionError(description.toString());
2223
}

0 commit comments

Comments
 (0)