Como usar o Mockito com JUnit5

102

Como posso usar injeção com Mockito e JUnit 5?

No JUnit4, posso apenas usar a @RunWith(MockitoJUnitRunner.class)Anotação. Em JUnit5 não há @RunWithanotação?

Daniel Käfer
fonte

Respostas:

144

Existem diferentes maneiras de usar o Mockito - irei examiná-las uma por uma.

Manualmente

A criação de simulações manualmente com Mockito::mockfunciona independentemente da versão do JUnit (ou estrutura de teste para esse assunto).

Com base em anotação

Usar a anotação @Mock e a chamada correspondente MockitoAnnotations::initMocks para criar simulações funciona independentemente da versão JUnit (ou estrutura de teste para esse assunto, mas Java 9 pode interferir aqui, dependendo se o código de teste termina em um módulo ou não).

Extensão Mockito

JUnit 5 tem um modelo de extensão poderoso e Mockito publicou recentemente um sob o ID de grupo / artefato org.mockito : mockito-junit-jupiter .

Você pode aplicar a extensão adicionando @ExtendWith(MockitoExtension.class)à classe de teste e anotando campos simulados com @Mock. Do MockitoExtensionJavaDoc de:

@ExtendWith(MockitoExtension.class)
public class ExampleTest {

    @Mock
    private List list;

    @Test
    public void shouldDoSomething() {
        list.add(100);
    }

}

A documentação do MockitoExtension descreve outras maneiras de instanciar mocks, por exemplo, com injeção de construtor (se você rpefer campos finais em classes de teste).

Sem regras, sem corredores

As regras e os corredores JUnit 4 não funcionam no JUnit 5, portanto, o MockitoRulee o corredor Mockito não podem ser usados.

Nicolai
fonte
6
Agora existe uma extensão oficial Mockito Junit5 que é o equivalente ao MockitoJUnitRunner -> mockito-junit-jupiter
dan carter
Quando a extensão oficial do Mockito foi lançada, escreveu uma postagem no blog com mais detalhes sobre como configurá-la e usá-la: solidsoft.wordpress.com/2018/03/27/…
Marcin Zajączkowski
O método anotado com @Testnecessidades para ser público ou "pacote privado" é bom o suficiente?
Geek
Ao executar testes com o Jupiter (freqüentemente referido como "JUnit 5"), os métodos de teste precisam apenas ser visíveis no pacote.
Nicolai
54

Use Mockito's MockitoExtension. A extensão está contida em um novo artefato mockito-junit-jupiter:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>

Ele permite que você escreva testes como faria com JUnit 4:

import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;

@ExtendWith(MockitoExtension.class)
class MyTest {

    @Mock
    private Foo foo;

    @InjectMocks
    private Bar bar; // constructor injection

    ...
}
Jonathan
fonte
4
@ExtendWith(MockitoExtension.class)é equivalente @RunWith(MockitoJUnitRunner.class)a do JUnit4
Sergey Nemchinov
8

Existem diferentes maneiras de fazer, mas a maneira mais limpa e que também respeita a filosofia do JUnit 5 é criar um org.junit.jupiter.api.extension.Extensionpara Mockito.

1) Criar mocks manualmente faz perder o benefício de verificações Mockito adicionais para garantir que você use a estrutura corretamente.

2) Chamar MockitoAnnotations.initMocks(this)todas as classes de teste é um código padrão que poderíamos evitar.
E fazer essa configuração em uma classe abstrata também não é uma boa solução.
Ele acopla todas as classes de teste a uma classe base.
Se precisar de uma nova classe de teste base por bons motivos, você termina com uma hierarquia de classes de 3 níveis. Por favor, evite isso.

3) Regras de teste é uma especificidade JUnit 4.
Nem pense nisso.
E a documentação é clara sobre isso:

No entanto, se você pretende desenvolver uma nova extensão para o JUnit 5, use o novo modelo de extensão do JUnit Jupiter em vez do modelo baseado em regras do JUnit 4.

4) O Test Runner não é realmente a maneira de estender a estrutura JUnit 5.
O JUnit 5 simplificou o inferno dos executores do JUnit 4, fornecendo um modelo de extensão para escrever testes graças ao JUnit 5 Extensions.
Nem pense nisso.

Portanto, favoreça o org.junit.jupiter.api.extension.Extensioncaminho.


EDITAR: Na verdade, o Mockito agrupa uma extensão Júpiter: mockito-junit-jupiter

Então, muito simples de usar:

import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class FooTest {
     ...    
}

Aqui está um complemento à excelente resposta de Jonathan.

Ao adicionar o mockito-junit-jupiterartefato como dependência , o uso @ExtendWith(MockitoExtension.class)produziu a seguinte exceção à medida que o teste é executado:

java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation (Ljava / util / Opcional; Ljava / lang / Class;) Ljava / util / Opcional;

O problema é que mockito-junit-jupiterdepende de duas bibliotecas independentes. Por exemplo mockito-junit-jupiter:2.19.0:

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>2.19.0</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
  <version>5.1.0</version>
  <scope>runtime</scope>
</dependency>

O problema foi que eu usei junit-jupiter-api:5.0.1.

Portanto, como junit-jupiter-apiainda se move frequentemente em termos de API, certifique-se de depender da mesma versão da junit-jupiter-apiqual mockito-junit-jupiterdepende.

davidxxx
fonte
por que não mockito-junit-jupiterpuxa a versão adequada de junit-jupiter-api?
haelix
@haelix Porque a estratégia de versão usada para esta dependência depende da biblioteca Mockito. Veja a versão aqui mockito-junit-jupiter:2.19.0. Enquanto as versões de JUnit Jupiter começam com 5. mockito-junit-jupiter deve ter especificado em seu identificador de artefato as duas coisas (versão Mockito e versão JUnit Júpiter) para tornar as coisas mais claras. Por exemplo, mockito-junit-jupiter-5.1:2.19.0para transmitir que a biblioteca foi projetada para JUnit Jupiter 5.1.
davidxxx
MockitoExtensionnão parece existir na mockito-coreversão 3.0.0.
Thunderforge
1
@Thunderforge Isso é definido emmockito-junit-jupiter
davidxxx de
3

Você tem que usar a nova @ExtendWithanotação.

Infelizmente, ainda não há nenhuma extensão lançada. No github, você pode ver uma implementação beta da extensão. como um exemplo de teste de demonstração .

Daniel Käfer
fonte