How to use JUnit and Hamcrest together?

69,402

Solution 1

junit provides new check assert methods named assertThat() which uses Matchers and should provide a more readable testcode and better failure messages.

To use this there are some core matchers included in junit. You can start with these for basic tests.

If you want to use more matchers you can write them by yourself or use the hamcrest lib.

The following example demonstrates how to use the empty matcher on an ArrayList:

package com.test;

import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

public class EmptyTest {
    @Test
    public void testIsEmpty() {
        List myList = new ArrayList();
        assertThat(myList, is(empty()));

    }
}

(I included the hamcrest-all.jar in my buildpath)

Solution 2

If you're using a Hamcrest with a version greater or equal than 1.2, then you should use the junit-dep.jar. This jar has no Hamcrest classes and therefore you avoid classloading problems.

Since JUnit 4.11 the junit.jar itself has no Hamcrest classes. There is no need for junit-dep.jar anymore.

Solution 3

Not exactly answering your question, but you should definitely try FEST-Assert fluent assertions API. It's competing with Hamcrest, but has a much easier API with only one static import required. Here is the code provided by cpater using FEST:

package com.test;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import static org.fest.assertions.Assertions.assertThat;

public class EmptyTest {
    @Test
    public void testIsEmpty() {
        List myList = new ArrayList();
        assertThat(myList).isEmpty();
    }  
}

EDIT: Maven coordinates:

<dependency>
  <groupId>org.easytesting</groupId>
  <artifactId>fest-assert</artifactId>
  <version>1.4</version>
  <scope>test</scope>
</dependency>

Solution 4

Also, if JUnit 4.1.1 + Hamcrest 1.3 + Mockito 1.9.5 are being used, make sure mockito-all is not used. It contains Hamcrest core classes. Use mockito-core instead. The below config works :

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <artifactId>hamcrest-core</artifactId>
            <groupId>org.hamcrest</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.1.1</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <artifactId>hamcrest-core</artifactId>
            <groupId>org.hamcrest</groupId>
        </exclusion>
    </exclusions>
</dependency>

Solution 5

Since versions are changing all the time, I'm posting to let people know that as of December 2, 2014, the instructions at http://www.javacodegeeks.com/2014/03/how-to-test-dependencies-in-a-maven-project-junit-mockito-hamcrest-assertj.html worked for me. I did not use AssertJ though, just these:

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>1.9.5</version>
  <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-core</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>   
<dependency>
    <groupId>org.objenesis</groupId>
    <artifactId>objenesis</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>
Share:
69,402
yegor256
Author by

yegor256

Lab director at Huawei, co-founder at Zerocracy, blogger at yegor256.com, author of Elegant Objects book; architect of Zold.

Updated on September 30, 2020

Comments

  • yegor256
    yegor256 over 3 years

    I can't understand how JUnit 4.8 should work with Hamcrest matchers. There are some matchers defined inside junit-4.8.jar in org.hamcrest.CoreMatchers. At the same time there are some other matchers in hamcrest-all-1.1.jar in org.hamcrest.Matchers. So, where to go? Shall I explicitly include hamcrest JAR into the project and ignore matchers provided by JUnit?

    In particular, I'm interested in empty() matcher and can't find it in any of these jars. I need something else? :)

    And a philosophical question: why JUnit included org.hamcrest package into its own distribution instead of encouraging us to use original hamcrest library?

  • yegor256
    yegor256 about 13 years
    where exactly org.hamcrest.Matchers.empty() is located? Could you please give a link to the JAR file?
  • cpater
    cpater about 13 years
    You can find all here: code.google.com/p/hamcrest and the download of hamcrest-all.jar here: code.google.com/p/hamcrest/downloads/…
  • yegor256
    yegor256 about 13 years
    Looks like hamcrest 1.2 is not in Maven Central repository. That's the problem I'm facing :(
  • cpater
    cpater about 13 years
    Ok in repo is only 1.1 and there is no empty Matcher. You can download the 1.2 jar and install it in your local repo: maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
  • Guillaume
    Guillaume about 12 years
    I just swapped my assertion library. I was quite satisfied with hamcrest, but because of the junit problematic inclusion stuff and some hard to write test (with collection and generics), I'm know in love with FEST! Thanks for sharing.
  • Tom
    Tom over 11 years
    Hamcrest 1.3 has now been released, and is in maven central.
  • Adrien Be
    Adrien Be over 11 years
  • Grundlefleck
    Grundlefleck about 11 years
    I thoroughly recommend using org.hamcrest.MatcherAssert.assertThat, rather than the JUnit version, as it will allow more descriptive error messages.
  • Jeff Evans
    Jeff Evans over 9 years
    It seems like as of JUnit 4.12, there is no longer a junit-dep.jar. Is that the case? And if so, are we meant to use the standalone Hamcrest 1.3 jar?
  • Stefan Birkner
    Stefan Birkner over 9 years
    Answer to both questions: yes.
  • user64141
    user64141 over 8 years
    FEST is no longer active. Use AssertJ, which is a fork of FEST. joel-costigliola.github.io/assertj
  • Dan Getz
    Dan Getz over 7 years
    I don't understand your second paragraph. I think you might have left out some words from what you meant to write?
  • Eugene Maysyuk
    Eugene Maysyuk over 5 years
    There is no need to define both hamcrest-core and hamcrest-library dependencies at the same time since the hamcrest-library already defines hamcrest-core as a transitive dependency.