Hamcrest is Junit`s Assert framework. Hamcrest provides a variety of matchers, allowing you to test the state of an object with compact code. Also, when a test fails, a detailed Failure message is printed out for what reason the test failed.
The term Hamcrest was coined by simply changing the alphabetic position of Matchers.
Matcher
A Matcher is an object that performs a match operation.
If you pass Object and Matcher as arguments to assertThat()
as follows, the Matcher checks whether the Object meets the expected condition. Depending on the matcher`s result, the test will pass or fail.
public void assertThat(Object o, Matcher matcher){
...
}
Why use Hamcrest?
By comparing the test using Junits Assert and the test using Hamcrest, let
s see the reason for using Hamcrest.
- Reading Failure Messages
- Readability of test code
- Various Matcher products
Readability of Failure messages
The code below is a basic Assert provided by Junit, and it is a test to check whether variables a and b are different.
@Test
public void test_using_junit() {
int a = 10;
int b = 10;
assertNotEquals(a, b);
}
The above test will of course fail, but if you look at the failure message, it is not clear what went wrong. If you look at the code with the log, you will understand that the test failed because a and b have the same value.
expected: not equal but was: <10>
org.opentest4j.AssertionFailedError: expected: not equal but was: <10>
The above code can also be implemented as a test using Hamcrest like this:
@Test
public void test_using_hamcrest() {
int a = 10;
int b = 10;
assertThat(a, is(not(equalTo(b))));
}
Of course, this test will also fail, but the failure log is easier to understand than the above log.
Expected: is not <10>
but: was <10>
Readability of test code (1)
assertNotEquals()
is an Assert provided by Junit by default. This Assert checks whether a and b passed as arguments are different. Its a simple code, so it
s not hard to understand.
assertNotEquals(a, b);
The following is a test code that checks the same conditions as above using Hamcrest. If you look at the code, it becomes a perfect English sentence unlike the above.
assertThat(a, is(not(equalTo(b))));
You might think that the above code is a bit unreadable because it is made of overly perfect sentences.
If you remove is()
as follows, the result is the same, and the code looks more concise.
assertThat(a, not(equalTo(b)));
Readability of test code (2)
You can write code to test if the str variable satisfies all three conditions, like this: Of course, it`s fine to test each with 3 asserts, but I assumed there are situations where you need to implement with 1 assert.
public void test_allOf() {
String str = "MyTest";
boolean result = str.equals("MyTest")
&& str.startsWith("My")
&& str.contains("Test");
assertTrue(result);
}
Hamcrest provides an allOf()
matcher, and the test succeeds only when all matchers passed as arguments pass. That is, allOf()
means AND in logical operator.
Instead of &&
, all Of
can be used to help understand the code.
@Test
public void test_allOf() {
String str = "MyTest";
assertThat(str, allOf(is("MyTest"),
startsWith("My"),
containsString("Test")));
}
Conversely, the Matcher corresponding to the logical operator OR is anyOf()
. If only one of the Matchers passed as arguments passes, the test will pass.
assertThat(str, anyOf(is("MyTest"),
startsWith("Me"),
containsString("Test")));
Provide various matchers
If you want to test that the absolute difference between a and b is less than 0.5, you can implement assertTrue like this:
@Test
public void test_closeTo() {
double a = 10.9;
double b = 10.0;
assertTrue(Math.abs(a-b) < 0.5);
}
However, this code is not very readable, and when it fails, it outputs a log that is difficult to understand why it failed, like this:
expected: <true> but was: <false>
Expected :true
Actual :false
Hamcrest provides a matcher called closeTo()
, which can be used to test whether the absolute difference is less than 0.5.
@Test
public void test_using_hamcrest3() {
double a = 10.9;
double b = 10.0;
assertThat(a, closeTo(b, 0.5));
}
When a test fails, a log of why it failed is also output.
Expected: a numeric value within <0.5> of <10.0>
but: <10.9> differed by <0.40000000000000036> more than delta <0.5>
Hamcrest provides various matchers in addition to closeTo()
. For more information about the API, refer to Hamcrest JavaDoc.
- allOf, anyOf
- not, is
- hasEntry, hasKey, hasValue
- closeTo
- greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo
- equalToIgnoringCase, equalToIgnoringWhiteSpace
- containsString, endsWith, startsWith
Related Posts
- Java - Remove items from List while iterating
- Java - How to find key by value in HashMap
- Java - Update the value of a key in HashMap
- Java - How to put quotes in a string
- Java - How to put a comma (,) after every 3 digits
- BiConsumer example in Java 8
- Java 8 - Consumer example
- Java 8 - BinaryOperator example
- Java 8 - BiPredicate Example
- Java 8 - Predicate example
- Java 8 - Convert Stream to List
- Java 8 - BiFunction example
- Java 8 - Function example
- Java - Convert List to Map
- Exception testing in JUnit
- Hamcrest Collections Matcher
- Hamcrest equalTo () Matcher
- AAA pattern of unit test (Arrange/Act/Assert)
- Hamcrest Text Matcher
- Hamcrest Custom Matcher
- Why Junit uses Hamcrest
- Java - ForkJoinPool
- Java - How to use Futures
- Java - Simple HashTable implementation
- Java - Create a file in a specific path
- Java - Mockito의 @Mock, @Spy, @Captor, @InjectMocks
- Java - How to write test code using Mockito
- Java - Synchronized block
- Java - How to decompile a ".class" file into a Java file (jd-cli decompiler)
- Java - How to generate a random number
- Java - Calculate powers, Math.pow()
- Java - Calculate the square root, Math.sqrt()
- Java - How to compare String (==, equals, compare)
- Java - Calculate String Length
- Java - case conversion & comparison insensitive (toUpperCase, toLowerCase, equalsIgnoreCase)