Matchers (JUnit 5, Hamcrest and AssertJ)
Table of contents
Hamcrest
Hamcrest is a framework for writing matcher objects allowing ‘match’ rules to be defined declaratively.
Add the Hamcrest dependency
dependencies { testImplementation 'org.hamcrest:hamcrest:2.2' }
Example
package demo; import org.junit.jupiter.api.Test; import java.math.BigDecimal; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.CombinableMatcher.either; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.Is.isA; import static org.hamcrest.core.IsEqual.equalTo; import static org.hamcrest.core.StringStartsWith.startsWith; import static org.hamcrest.number.IsCloseTo.closeTo; import static org.hamcrest.number.OrderingComparison.comparesEqualTo; import static org.hamcrest.number.OrderingComparison.greaterThan; import static org.hamcrest.number.OrderingComparison.lessThan; class AppTest { @Test public void tryingOutHamcrest() { assertThat( "my string", equalTo( "my string" ) ); assertThat( "Hello everyone", startsWith( "Hello" ) ); assertThat( 10, is( greaterThan( 5 ) ) ); assertThat( 10, isA( Integer.class ) ); assertThat( 10, either( greaterThan( 50 ) ).or( lessThan( 20 ) ) ); assertThat( new BigDecimal( "10" ), comparesEqualTo( new BigDecimal( "10.00" ) ) ); assertThat( 10.01, closeTo( 10, 0.02 ) ); } }
AssertJ
Assertj is a java library providing a rich set of assertions, truly helpful error messages, improves test code readability and is designed to be super easy to use.
Add the Assertj dependency
dependencies { testImplementation 'org.assertj:assertj-core:3.16.1' }
Example
package demo; import org.junit.jupiter.api.Test; import java.math.BigDecimal; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.offset; class AppTest { @Test public void tryingOutAssertJ() { assertThat( "my string" ).isEqualTo( "my string" ); assertThat( "Hello everyone" ).startsWith( "Hello" ); assertThat( 10 ).isGreaterThan( 5 ); assertThat( 10 ).isInstanceOfAny( Integer.class ); /* Using Lambdas here */ assertThat( 10 ).satisfiesAnyOf( i -> assertThat( i ).isGreaterThan( 50 ), i -> assertThat( i ).isLessThan( 20 ) ); assertThat( new BigDecimal( "10" ) ).isEqualByComparingTo( new BigDecimal( "10.00" ) ); assertThat( 10.01 ).isCloseTo( 10, offset( 0.02 ) ); } }
JUnit 5, Hamcrest and AssertJ
Library | Test Runner | Matcher |
---|---|---|
JUnit 5 | YES | YES |
Hamcrest | NO | YES |
AssertJ | NO | YES |
According to Google Trends, the matchers share similar popularity.
The good news is that these are not mutually exclusive and it is not uncommon to find them both.
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.0-M1'
testImplementation 'org.hamcrest:hamcrest:2.2'
testImplementation 'org.assertj:assertj-core:3.16.1'
}
With that said, using both Hamcrest and AssertJ may be challenging as both use the same method name assertThat()
and thus cannot just static import this method.
package demo;
import org.assertj.core.api.Assertions;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
class AppTest {
@Test
public void tryingOutBothInSameTest() {
Assertions.assertThat( 10 ).isEqualTo( 10 );
MatcherAssert.assertThat( 10, Matchers.equalTo( 10 ) );
}
}