Como usar JUnit e Hamcrest juntos?

87

Não consigo entender como o JUnit 4.8 deve funcionar com os matchers Hamcrest. Existem alguns matchers definidos dentro junit-4.8.jarde org.hamcrest.CoreMatchers. Ao mesmo tempo, existem alguns outros matchers hamcrest-all-1.1.jarem org.hamcrest.Matchers. Então, para onde ir? Devo incluir explicitamente o JAR do hamcrest no projeto e ignorar os correspondentes fornecidos pelo JUnit?

Em particular, estou interessado no empty()matcher e não consigo encontrá-lo em nenhum desses potes. Eu preciso de mais alguma coisa? :)

E uma questão filosófica: por que JUnit incluiu o org.hamcrestpacote em sua própria distribuição em vez de nos encorajar a usar a biblioteca original do hamcrest?

Yegor256
fonte

Respostas:

49

O junit fornece novos métodos de verificação de declaração chamados assertThat (), que usa Matchers e deve fornecer um código de teste mais legível e melhores mensagens de falha.

Para usar isso, existem alguns matchers principais incluídos no junit. Você pode começar com eles para testes básicos.

Se você quiser usar mais matchers, você pode escrevê-los sozinho ou usar a biblioteca hamcrest.

O exemplo a seguir demonstra como usar o matcher vazio em um 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()));

    }
}

(Eu incluí o hamcrest-all.jar no meu buildpath)

cpater
fonte
2
onde exatamente org.hamcrest.Matchers.empty()está localizado? Você poderia fornecer um link para o arquivo JAR?
yegor256
Você pode encontrar tudo aqui: code.google.com/p/hamcrest e o download de hamcrest-all.jar aqui: code.google.com/p/hamcrest/downloads/…
cpater
1
Parece que o hamcrest 1.2 não está no repositório Maven Central. Esse é o problema que estou enfrentando :(
yegor256
5
O Hamcrest 1.3 já foi lançado e está no maven central.
Tom
50

Se estiver usando um Hamcrest com uma versão maior ou igual a 1.2, você deve usar o junit-dep.jar. Este jar não tem classes Hamcrest e, portanto, você evita problemas de carregamento de classe.

Desde o JUnit 4.11, o junit.jarpróprio não tem classes Hamcrest. Não há necessidade de junit-dep.jarmais.

Stefan Birkner
fonte
2
Parece que a partir do JUnit 4.12, não há mais um junit-dep.jar. É esse o caso? E em caso afirmativo, devemos usar o frasco autônomo do Hamcrest 1.3?
Jeff Evans
1
Responda a ambas as perguntas: sim.
Stefan Birkner
25

Não respondendo exatamente à sua pergunta, mas você definitivamente deve tentar a API de asserções fluentes do FEST-Assert . Ele está competindo com o Hamcrest, mas tem uma API muito mais fácil com apenas uma importação estática necessária. Aqui está o código fornecido por cpater usando 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();
    }  
}

EDITAR: Coordenadas Maven:

<dependency>
  <groupId>org.easytesting</groupId>
  <artifactId>fest-assert</artifactId>
  <version>1.4</version>
  <scope>test</scope>
</dependency>
Tomasz Nurkiewicz
fonte
3
Acabei de trocar minha biblioteca de asserções. Fiquei bastante satisfeito com o hamcrest, mas por causa do material problemático de inclusão do junit e alguns testes difíceis de escrever (com coleção e genéricos), sou apaixonado pelo FEST! Obrigado por compartilhar.
Guillaume
2
O FEST não está mais ativo. Use AssertJ, que é um fork do FEST. joel-costigliola.github.io/assertj
user64141
17

Além disso, se JUnit 4.1.1 + Hamcrest 1.3 + Mockito 1.9.5 estiver sendo usado, certifique-se de que o mockito-all não seja usado. Ele contém as classes principais do Hamcrest. Em vez disso, use o mockito-core. A configuração abaixo funciona:

<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>
souser
fonte
4

Como as versões estão mudando o tempo todo, estou postando para que as pessoas saibam que, a partir de 2 de dezembro de 2014, as instruções em http://www.javacodegeeks.com/2014/03/how-to-test-dependencies-in -a-maven-project-junit-mockito-hamcrest-assertj.html funcionou para mim. Eu não usei AssertJ, porém, apenas estes:

<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>
Michael Osofsky
fonte
1
Não há necessidade de definir as dependências hamcrest-core e hamcrest-library ao mesmo tempo, uma vez que a hamcrest-library já define hamcrest-core como uma dependência transitiva.
Eugene Maysyuk
3

por que JUnit incluiu o pacote org.hamcrest em sua própria distribuição em vez de nos encorajar a usar a biblioteca original do hamcrest?

Eu acho que é porque eles queriam assertThatfazer parte do JUnit. Isso significa que a Assertclasse precisa importar a org.hamcrest.Matcherinterface e não pode fazer isso a menos que JUnit dependa de Hamcrest ou inclua (pelo menos parte de) Hamcrest. E acho que incluir parte dele foi mais fácil, de modo que JUnit pudesse ser usado sem quaisquer dependências.

MatrixFrog
fonte
2

Em 2018, usando a maioria das bibliotecas modernas:

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")
}
Gavenkoa
fonte
0

Tanto o JUnit-4.12 quanto o JUnit-Dep-4.10 têm dependências do Hamcrest de acordo com os respectivos arquivos .xml.

Uma investigação mais aprofundada mostra que, embora a dependência tenha sido feita nos arquivos .xml, a origem e as classes nos jars. Isso parece ser uma forma de excluir a dependência em build.gradle ... testá-lo para manter tudo limpo.

Apenas um fyi

cyclops3324911
fonte
1
Eu não entendo seu segundo parágrafo. Acho que você pode ter omitido algumas palavras do que pretendia escrever.
Dan Getz