In the post Improving On assertEquals with JUnit and Hamcrest I introduced use of Hamcrest with JUnit. I then looked at JUnit's Built-in Hamcrest Core Matcher Support. In this post, I look at how to apply Hamcrest's non-core matchers with JUnit. These non-core matchers are NOT included with JUnit by default, but are available by including a Hamcrest JAR in the classpath.
Although JUnit's inclusion of Hamcrest core matchers makes them easier to use if one only wants to use the core matchers, this inclusion can make use of the non-core matchers more difficult and is a well-known issue.
Because the non-core Hamcrest matchers are not included with JUnit, the Hamcrest JAR needs to be downloaded. For my examples in this post, I am using hamcrest-all-1.2.jar.
The next screen snapshot indicates the problems with combining the hamcrest-all JAR with the normal JUnit library (JUnit 4.10 as provided by NetBeans 7.2 beta in my example). As the screen snapshot indicates, when the junit-4.10.jar
is included in the NetBeans libraries BEFORE the hamcrest-all-1.2.jar
, the previously working code (from my previous post) breaks. Both NetBeans and the command-line compiler show this breakage in this screen snapshot.
Switching the order of the test libraries so that the Hamcrest library is listed first and the JUnit JAR listed after it, makes the compiler break on the test code go away. This is shown in the next screen snapshot.
Although switching the order of the dependent libraries so that the Hamcrest JAR is included before the JUnit JAR does prevent the build problem, this is not typically a satisfactory approach. This approach is too fragile for long-term maintainability. Fortunately, there is a better approach that JUnit directly supports to deal with this issue.
A special Hamcrest-less JUnit JAR can be downloaded. The next screen snapshot shows the one I use in this example: junit-dep-4.10.jar
. The -dep
in the JAR name is the clue that it's Hamcrest-free. The notation next to the JAR on the download page (screen snapshot shown next) points this out as well ("Jar without hamcrest").
With the Hamcrest-free "dep" version of the JUnit JAR, I can include it in the test libraries at any point I like with relation to the Hamcrest JAR and will still be able to build the test code. This is a much more favorable approach than relying on a specific order of test libraries. The next image shows the screen snapshot of NetBeans and the command-line build being successful even with the JUnit JAR listed first.
With the appropriate libraries in use (JUnit-dep JAR and the Hamcrest "all" JAR), all of Hamcrest's matchers can be used with JUnit-based tests. Hamcrest provides numerous matchers beyond the core matches that are now bundled with JUnit. One way to get an idea of the additional matchers available is to look at the classes in the Hamcrest JAR. The following is output from running a jar tvf
command against the Hamcrest JAR and removing many of the entries to leave some of the most interesting ones. The "core" matchers tend to be based on the classes in the "core" package and the non-core matchers tend to be based on the classes in all the other packages without "core" in their name.
4029 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/AllOf.java 3592 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/AnyOf.java 1774 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/CombinableMatcher.java 1754 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/DescribedAs.java 1104 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/Every.java 2088 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/Is.java 1094 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/IsAnything.java 2538 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/IsCollectionContaining.java 1862 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/IsEqual.java 2882 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/IsInstanceOf.java 1175 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/IsNot.java 1230 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/IsNull.java 960 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/IsSame.java 675 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/StringContains.java 667 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/StringEndsWith.java 678 Thu May 21 23:21:20 MDT 2009 org/hamcrest/core/StringStartsWith.java 2557 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsArray.java 1805 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsArrayContaining.java 1883 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsArrayContainingInAnyOrder.java 1765 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsArrayContainingInOrder.java 1388 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsArrayWithSize.java 1296 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsCollectionWithSize.java 812 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsEmptyCollection.java 866 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsEmptyIterable.java 1086 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsIn.java 3426 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsIterableContainingInAnyOrder.java 3479 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsIterableContainingInOrder.java 993 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsIterableWithSize.java 1899 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsMapContaining.java 1493 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsMapContainingKey.java 1421 Thu May 21 23:21:20 MDT 2009 org/hamcrest/collection/IsMapContainingValue.java 1380 Thu May 21 23:21:20 MDT 2009 org/hamcrest/number/IsCloseTo.java 2878 Thu May 21 23:21:20 MDT 2009 org/hamcrest/number/OrderingComparison.java 1082 Thu May 21 23:21:20 MDT 2009 org/hamcrest/object/HasToString.java 918 Thu May 21 23:21:20 MDT 2009 org/hamcrest/object/IsCompatibleType.java 2080 Thu May 21 23:21:20 MDT 2009 org/hamcrest/object/IsEventFrom.java 1164 Thu May 21 23:21:20 MDT 2009 org/hamcrest/text/IsEmptyString.java 1389 Thu May 21 23:21:20 MDT 2009 org/hamcrest/text/IsEqualIgnoringCase.java 2058 Thu May 21 23:21:20 MDT 2009 org/hamcrest/text/IsEqualIgnoringWhiteSpace.java 1300 Thu May 21 23:21:20 MDT 2009 org/hamcrest/text/StringContainsInOrder.java 4296 Thu May 21 23:21:20 MDT 2009 org/hamcrest/xml/HasXPath.java
JUnit's providing of a JAR without Hamcrest automatically built in (the "dep" JAR) allows developers to more carefully building up their classpaths if Hamcrest matchers above and beyond the "core" matchers are desired for use with JUnit.
2 comments:
It looks like junit-dep-2.10.jar still depends on hamcrest-core-1.1.jar
So I cannot use hamcrest-core-1.3.jar
If you are using maven you can exlude that dependency with:
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
Post a Comment