How to use JUnit and Hamcrest together?
Asked Answered
C

8

93

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?

Cobwebby answered 6/4, 2011 at 15:56 Comment(0)
B
51

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)

Bagdad answered 6/4, 2011 at 16:29 Comment(7)
where exactly org.hamcrest.Matchers.empty() is located? Could you please give a link to the JAR file?Cobwebby
You can find all here: code.google.com/p/hamcrest and the download of hamcrest-all.jar here: code.google.com/p/hamcrest/downloads/…Bagdad
Looks like hamcrest 1.2 is not in Maven Central repository. That's the problem I'm facing :(Cobwebby
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.htmlBagdad
Hamcrest 1.3 has now been released, and is in maven central.Rogerson
A relevant comment from Stefan Birkner in the answers 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.Apoplexy
I thoroughly recommend using org.hamcrest.MatcherAssert.assertThat, rather than the JUnit version, as it will allow more descriptive error messages.Colley
N
53

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.

Nolitta answered 8/9, 2011 at 19:42 Comment(2)
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?Marleah
Answer to both questions: yes.Nolitta
B
51

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)

Bagdad answered 6/4, 2011 at 16:29 Comment(7)
where exactly org.hamcrest.Matchers.empty() is located? Could you please give a link to the JAR file?Cobwebby
You can find all here: code.google.com/p/hamcrest and the download of hamcrest-all.jar here: code.google.com/p/hamcrest/downloads/…Bagdad
Looks like hamcrest 1.2 is not in Maven Central repository. That's the problem I'm facing :(Cobwebby
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.htmlBagdad
Hamcrest 1.3 has now been released, and is in maven central.Rogerson
A relevant comment from Stefan Birkner in the answers 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.Apoplexy
I thoroughly recommend using org.hamcrest.MatcherAssert.assertThat, rather than the JUnit version, as it will allow more descriptive error messages.Colley
D
25

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>
Drunk answered 6/4, 2011 at 16:59 Comment(2)
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.Cellarer
FEST is no longer active. Use AssertJ, which is a fork of FEST. joel-costigliola.github.io/assertjHousehold
K
19

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>
Kickshaw answered 13/1, 2014 at 17:48 Comment(0)
C
4

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>
Canzonet answered 2/12, 2014 at 17:47 Comment(1)
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.Infuse
C
3

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

I would guess that's because they wanted the assertThat to be part of JUnit. So that means the Assert class has to import the org.hamcrest.Matcher interface and it can't do that unless JUnit either depends on Hamcrest, or includes (at least part of) Hamcrest. And I guess including part of it was easier, so that JUnit would be usable without any dependencies.

Creditable answered 30/6, 2011 at 0:19 Comment(0)
B
2

In 2018 using most modern libraries:

configurations {
    all {
        testCompile.exclude group: "org.hamcrest", module: "hamcrest-core"
        testCompile.exclude group: "org.hamcrest", module: "hamcrest-library"
    }
}
dependencies {
    testCompile("junit:junit:4.12")
    // testCompile("org.hamcrest:hamcrest-library:1.3")
    // testCompile("org.hamcrest:java-hamcrest:2.0.0.0")
    testCompile("org.hamcrest:hamcrest-junit:2.0.0.0")
}
Buddhology answered 29/9, 2018 at 22:49 Comment(0)
G
0

Both JUnit-4.12 and JUnit-Dep-4.10 has Hamcrest dependencies according to the respective .xml files.

Further investigation shows that although the dependency was made in the .xml files, the source and classes in the jars. The seems to be a way of excluding the dependency in build.gradle ... testing it out to keep everything clean.

Just an f.y.i.

Groome answered 12/9, 2015 at 0:20 Comment(1)
I don't understand your second paragraph. I think you might have left out some words from what you meant to write?Obola

© 2022 - 2024 — McMap. All rights reserved.