Comparação entre Mockito x JMockit - por que Mockito foi votado melhor que o JMockit? [fechadas]

124

Estou investigando qual estrutura de simulação usar no meu projeto e a reduzi a JMockit e Mockito .

Percebo que o Mockito foi eleito " o melhor framework simulado para Java " no Stackoverflow.
Na comparação de características em JMockit 's ' Mocking Ferramenta de Comparação Matrix ' parece que JMockit tem várias características diferentes.

Alguém tem alguma informação específica (não opiniões) sobre o que o Mockito pode fazer e que não pode ser alcançado com o JMockit e vice-versa?

Rogério
fonte
2
talvez melhor usabilidade para Mockito, btw eu não acho que JMockit é mais maduro do que Mockito ...
Alois Cochard
42
A julgar pelo número de votos, OBVIOMENTE as respostas a esta pergunta são muito procuradas pela comunidade. O que significa que a estratégia ortogonalizadora deste site que fez com que essa pergunta fosse fechada precisa de uma séria repensação - pois esse site frequentemente se esforça para fornecer as respostas necessárias ao cair na ortogonalidade desalinhada. Sem perceber que na análise gráfica de uma árvore, existem tantas maneiras de visualizar a ortogonalidade de uma árvore quanto existem nós. Talvez a ortogonalidade deste site, em vez da pergunta, esteja desalinhada.
Blessed Geek
9
+1 por não fechar. Essas respostas têm muito valor. Escolher uma tecnologia não é fácil e essas perguntas podem economizar muito tempo. De fato, pode não haver uma resposta certa, mas o StackOverflow deve acomodar perguntas sem um aswer.
Mhstnsc
6
Acrescentarei meu apoio àqueles que afirmam que fechar isso como "não construtivo" é ridículo. As respostas fornecidas aqui foram apoiadas por "fatos, referências e / ou conhecimentos". Uma pergunta no campo da tecnologia que não solicita alguns "debates, pesquisas ou discussões prolongadas" geralmente não vale a pena perguntar. Além disso, o fornecimento de fatos e conhecimentos se baseia em experiências diferentes - e essas diferenças levarão ao debate e a discussões prolongadas.
Jeff Nyman
@Alois - você pode dar exemplos concretos em que o JMockit parece menos maduro que o Mockito?
NitinS

Respostas:

140

Atualização em setembro de 2019: A única estrutura de simulação suportada (por padrão) pelo Spring Boot é o Mockito . Se você usa o Spring, a resposta é bastante óbvia.


Eu diria que a competição é entre JMockit e PowerMock , depois Mockito .

Eu deixaria o jMock e o EasyMock "simples" porque eles usam apenas proxy e CGLIB e não usam a instrumentação Java 5 como as estruturas mais recentes.

O jMock também não possui uma versão estável há mais de 4 anos. O jMock 2.6.0 exigiu 2 anos para passar de RC1 para RC2 e mais 2 anos antes de ser lançado.

Em relação ao Proxy e CGLIB vs instrumentação:

(EasyMock e jMock) são baseados em java.lang.reflect.Proxy, que requer que uma interface seja implementada. Além disso, eles suportam a criação de objetos simulados para classes através da geração de subclasse CGLIB. Por esse motivo, as referidas classes não podem ser finais e apenas métodos de instância substituíveis podem ser ridicularizados. Mais importante, no entanto, ao usar essas ferramentas, as dependências do código em teste (ou seja, os objetos de outras classes das quais depende uma determinada classe em teste) devem ser controladas pelos testes, para que instâncias simuladas possam ser transmitidas aos clientes dessas dependências. Portanto, as dependências não podem simplesmente ser instanciadas com o novo operador em uma classe cliente para a qual queremos escrever testes de unidade.

Por fim, as limitações técnicas das ferramentas de simulação convencionais impõem as seguintes restrições de design no código de produção:

  1. Cada classe que pode precisar ser ridicularizada em um teste deve implementar uma interface separada ou não ser final.
  2. As dependências de cada classe a ser testada devem ser obtidas por meio de métodos configuráveis ​​de criação de instância (fábricas ou um Localizador de Serviço) ou expostas para injeção de dependência. Caso contrário, os testes de unidade não poderão passar implementações simuladas de dependências para a unidade em teste.
  3. Como apenas métodos de instância podem ser zombados, as classes a serem testadas em unidade não podem chamar métodos estáticos em suas dependências, nem instancia-las usando qualquer um dos construtores.

O acima é copiado de http://jmockit.org/about.html . Além disso, ele compara entre si (JMockit), PowerMock e Mockito de várias maneiras:

Agora existem outras ferramentas de simulação para Java que também superam as limitações das convencionais, entre elas PowerMock, jEasyTest e MockInject. O que mais se aproxima do conjunto de recursos do JMockit é o PowerMock, então eu o avaliarei brevemente aqui (além disso, os outros dois são mais limitados e não parecem mais ser desenvolvidos ativamente).

JMockit vs PowerMock

  • Primeiro, o PowerMock não fornece uma API completa para zombaria, mas funciona como uma extensão para outra ferramenta, que atualmente pode ser EasyMock ou Mockito. Obviamente, isso é uma vantagem para os usuários existentes dessas ferramentas.
  • O JMockit, por outro lado, fornece APIs totalmente novas, embora sua API principal (Expectativas) seja semelhante ao EasyMock e ao jMock. Embora isso crie uma curva de aprendizado mais longa, também permite que o JMockit forneça uma API mais simples, consistente e fácil de usar.
  • Comparada à API do JMockit Expectations, a API do PowerMock é mais "de baixo nível", forçando os usuários a descobrir e especificar quais classes precisam ser preparadas para teste (com a anotação @PrepareForTest ({ClassA.class, ...}) ) e exigindo chamadas de API específicas para lidar com vários tipos de construções de linguagem que podem estar presentes no código de produção: métodos estáticos (mockStatic (ClassA.class)), construtores (suprimir (construtor (ClassXyz.class))), invocações de construtores ( expectNew (AClass.class)), simulações parciais (createPartialMock (ClassX.class, "methodToMock"))) etc.
  • Com o JMockit Expectations, todos os tipos de métodos e construtores são zombados de maneira puramente declarativa, com zombarias parciais especificadas por meio de expressões regulares na anotação @Mocked ou simplesmente "zombando" dos membros sem expectativas registradas; ou seja, o desenvolvedor simplesmente declara alguns "campos simulados" compartilhados para a classe de teste ou alguns "campos simulados locais" e / ou "parâmetros simulados" para métodos de teste individuais (e, neste último caso, a anotação @Mocked geralmente não necessário).
  • Alguns recursos disponíveis no JMockit, como suporte para zombar de iguais e hashCode, métodos substituídos e outros, atualmente não são suportados no PowerMock. Além disso, não há equivalente à capacidade do JMockit de capturar instâncias e implementações simuladas de tipos de base especificados à medida que o teste é executado, sem que o próprio código de teste tenha conhecimento das classes de implementação reais.
  • O PowerMock usa carregadores de classes personalizados (geralmente um por classe de teste) para gerar versões modificadas das classes simuladas. Esse uso pesado de carregadores de classe personalizados pode levar a conflitos com bibliotecas de terceiros, portanto, às vezes, é necessário usar a anotação @PowerMockIgnore ("package.to.be.ignored") nas classes de teste.
  • O mecanismo usado pelo JMockit (instrumentação de tempo de execução por meio de um "agente Java") é mais simples e seguro, embora exija a passagem de um parâmetro "-javaagent" para a JVM durante o desenvolvimento no JDK 1.5; no JDK 1.6+ (que sempre pode ser usado para desenvolvimento, mesmo que a implementação em uma versão mais antiga) não existe esse requisito, pois o JMockit pode carregar de forma transparente o agente Java sob demanda usando a API Attach.

Outra ferramenta de zombaria recente é o Mockito. Embora não tente superar as limitações das ferramentas mais antigas (jMock, EasyMock), ele introduz um novo estilo de teste de comportamento com zombarias. O JMockit também suporta esse estilo alternativo, por meio da API de verificações.

JMockit vs Mockito

  • O Mockito depende de chamadas explícitas à sua API para separar o código entre as fases de registro (quando (...)) e verificação (verificação (...)). Isso significa que qualquer chamada para um objeto simulado no código de teste também exigirá uma chamada para a API de simulação. Além disso, isso geralmente leva a chamadas repetitivas quando (...) e verifica (zomba) ...
  • Com o JMockit, não há chamadas semelhantes. Certamente, temos as novas chamadas de construtor NonStrictExpectations () e Verifications (), mas elas ocorrem apenas uma vez por teste (normalmente) e são completamente separadas das invocações para métodos e construtores simulados.
  • A API do Mockito contém várias inconsistências na sintaxe usada para invocações para métodos simulados. Na fase de registro, temos chamadas como when (mock.mockedMethod (args)) ... enquanto na fase de verificação essa mesma chamada será gravada como Verifique (mock) .mockedMethod (args). Observe que, no primeiro caso, a chamada para mockedMethod é feita diretamente no objeto simulado, enquanto no segundo caso, é feita no objeto retornado pela verificação (simulação).
  • O JMockit não possui essas inconsistências porque as invocações para métodos simulados são sempre feitas diretamente nas próprias instâncias simuladas. (Com apenas uma exceção: para combinar chamadas na mesma instância simulada, uma chamada onInstance (mock) é usada, resultando em código como onInstance (mock) .mockedMethod (args); a maioria dos testes não precisará usar isso. )
  • Assim como outras ferramentas de simulação que dependem do encadeamento / encapsulamento de métodos, o Mockito também apresenta uma sintaxe inconsistente ao remover métodos anulados. Por exemplo, você escreve when (mockedList.get (1)). ThenThrow (new RuntimeException ()); para um método não nulo e doThrow (new RuntimeException ()). when (mockedList) .clear (); por um vazio. Com o JMockit, é sempre a mesma sintaxe: mockedList.clear (); resultado = nova RuntimeException () ;.
  • Ainda outra inconsistência ocorre no uso de espiões de Mockito: "zombarias" que permitem que os métodos reais sejam executados na instância de espionagem. Por exemplo, se spy refere-se a uma lista vazia, em vez de escrever when (spy.get (0)). ThenReturn ("foo"), você precisará escrever doReturn ("foo"). When (spy) .get ( 0) Com o JMockit, o recurso de zombaria dinâmica fornece funcionalidade semelhante aos espiões, mas sem esse problema, pois os métodos reais são executados apenas durante a fase de reprodução.
  • No EasyMock e no jMock, as primeiras APIs de simulação para Java, o foco era inteiramente o registro de chamadas esperadas de métodos simulados, para objetos simulados que (por padrão) não permitem invocações inesperadas. Essas APIs também fornecem a gravação de invocações permitidas para objetos simulados que permitem invocações inesperadas, mas isso foi tratado como um recurso de segunda classe. Além disso, com essas ferramentas, não há como verificar explicitamente as invocações para zombarias após o exercício do código em teste. Todas essas verificações são realizadas de forma implícita e automática.
  • No Mockito (e também no Unitils Mock), o ponto de vista oposto é adotado. Todas as invocações para zombar de objetos que possam ocorrer durante o teste, gravadas ou não, são permitidas, nunca esperadas. A verificação é realizada explicitamente depois que o código em teste é exercido, nunca automaticamente.
  • Ambas as abordagens são muito extremas e, consequentemente, inferiores ao ideal. O JMockit Expectations & Verifications é a única API que permite ao desenvolvedor escolher perfeitamente a melhor combinação de invocações simuladas estritas (esperadas por padrão) e não estritas (permitidas por padrão) para cada teste.
  • Para ser mais claro, a API do Mockito tem as seguintes deficiências. Se você precisar verificar se uma chamada para um método simulado não nulo ocorreu durante o teste, mas o teste exigir um valor de retorno daquele método diferente do padrão para o tipo de retorno, o teste de Mockito terá código duplicado: uma chamada when (mock.someMethod ()). thenReturn (xyz) na fase de registro e uma verificação (mock) .someMethod () na fase de verificação. Com o JMockit, uma expectativa estrita sempre pode ser registrada, o que não precisará ser verificado explicitamente. Como alternativa, uma restrição de contagem de chamadas (vezes = 1) pode ser especificada para qualquer expectativa não estrita registrada (com o Mockito essas restrições podem ser especificadas apenas em uma chamada de verificação (simulação, restrição)).
  • O Mockito possui uma sintaxe ruim para verificações em ordem e para verificações completas (ou seja, verificar se todas as chamadas para objetos simulados são explicitamente verificadas). No primeiro caso, um objeto extra precisa ser criado e as chamadas para verificação são feitas: InOrder inOrder = inOrder (mock1, mock2, ...). No segundo caso, é necessário fazer chamadas como confirmNoMoreInteractions (mock) ou confirmZeroInteractions (mock1, mock2).
  • Com o JMockit, você simplesmente escreve novas VerificationsInOrder () ou novas FullVerifications () em vez de novas Verifications () (ou novas FullVerificationsInOrder () para combinar os dois requisitos). Não há necessidade de especificar quais objetos simulados estão envolvidos. Nenhuma chamada API de zombaria extra. E como bônus, chamando unverifiedInvocations () dentro de um bloco de verificação ordenado, você pode executar verificações relacionadas a pedidos que são simplesmente impossíveis no Mockito.

Por fim, o JMockit Testing Toolkit tem um escopo mais amplo e objetivos mais ambiciosos do que outros kits de ferramentas de simulação, a fim de fornecer uma solução completa e sofisticada de teste de desenvolvedor. Uma boa API para zombaria, mesmo sem limitações artificiais, não é suficiente para a criação produtiva de testes. Uma ferramenta de cobertura de código independente do IDE, fácil de usar e bem integrada também é essencial, e é isso que o JMockit Coverage visa fornecer. Outra parte do conjunto de ferramentas de teste do desenvolvedor que se tornará mais útil à medida que o conjunto de testes aumenta de tamanho é a capacidade de executar novamente testes de forma incremental após uma alteração localizada no código de produção; isso também está incluído na ferramenta Cobertura.

(concedido, a fonte pode ser tendenciosa, mas bem ...)

Eu diria que vá com o JMockit . É o mais fácil de usar, flexível e funciona em praticamente todos os casos, inclusive nos mais difíceis e nos cenários em que você não pode controlar a classe a ser testada (ou não pode quebrá-la devido a motivos de compatibilidade etc.).

Minhas experiências com o JMockit foram muito positivas.

Hendy Irawan
fonte
1
Eu nunca usei o jmockit, mas gostaria de adicionar outro argumento à discussão: dê uma olhada em uma comparação de tendências do Google de todas as estruturas discutidas. Desde 06.06.2012, o JMockit nem aparece no gráfico de tendências do Google quando comparado ao Mockito e EasyMock. E o número de usuários também é importante ao escolher uma estrutura.
máquinas
3
Isso é bem estranho. Mockito e JMockIt me dá respectivamente 409 'e 83' hits no google. Certamente JMockIt deve aparecer pelo menos.
thoredge
5
Sua resposta é muito útil. Planejei simplesmente usar o Mockito, mas agora testarei o JMockit primeiro. Parece bom demais para não tentar. @machinery: Sim, é importante observar as tendências, mas escolhê-las como critério principal o restringirá ao fluxo principal e o protegerá da inovação.
Deamon
1
Eu sei que esse é um tópico antigo, mas depois de ler esta resenha, pensei em tentar também. Devo dizer que, na superfície, o JMockit é muito promissor. No entanto, até o momento, tenho encontrado muito pouco apoio da comunidade. Estou tendo um grande problema com o meu entendimento da API Mock e, depois de postar meus problemas, não recebi resposta nos dois dias.
Eric B.
1
A resposta é 8 anos, muitas coisas na resposta não estão mais corretas. Um ponto é que o JMockit requer -javaagentsinalizador desde 1,42 porque você não pode se auto-conectar mais desde o Java 9 e encontrar soluções alternativas adequadas obviamente não estava no escopo do desenvolvedor. Outro ponto é que o JMockit não permite mais zombar de métodos e construtores privados, enquanto o PowerMock faz o mesmo.
Vampiro
24

Trabalhei com Mockito e JMockit, e minha experiência com eles é:

  • Mockito:

    • zombaria implícita (-> melhor usabilidade, mas tem o risco de não detectar chamadas de método não permitidas em zombarias)
    • verificação explícita
  • EasyMock:

    • zombaria explícita
    • verificação implícita
  • JMockit:

    • suporta ambos
  • Além disso, outros benefícios do JMockit:

    • se você estiver zombando de métodos / construtores estáticos etc. (como estender uma base de código legada muito antiga sem UT), terá duas opções: 1) Mockito / EasyMock com extensão Powermock ou 2) Jmockit
    • relatório de cobertura incorporado

Pessoalmente, prefiro o JMockit, que acho que é mais rico em recursos e flexível, mas requer uma curva de aprendizado um pouco mais acentuada. Geralmente, existem várias maneiras de obter o mesmo efeito de zombaria e requer mais cuidado ao projetar as zombarias.

Tumer
fonte
existe stackoverflow.com/questions/8003278/… "confirmNoMoreInteractions" Suponho que se você quiser zombar pseudo-explícito com mockito
rogerdpack
15

Eu uso o jMockit apenas por causa de suas bibliotecas de reflexão no Deencapsultation.class. Na verdade, eu amo o estilo de Mockito, mas recuso-me a alterar meu código e a alterar minha API apenas para que uma estrutura de teste limitada possa chegar a ele. E eu sou fã de testar todo o meu código, portanto, uma estrutura que não pode testar facilmente métodos privados não é o que eu quero usar.

Eu fui influenciado por este artigo

Após uma curva de aprendizado (reconhecidamente grande), o jMockit agora é minha principal estrutura de teste de unidades para zombarias.

Joseph Erickson
fonte
7
Talvez se você sentir que precisa testar métodos particulares, esteja preocupado demais com o funcionamento do seu código, e não com o que ele faz (qual é o ponto real e que pode ser determinado pelo exercício apenas de seus métodos públicos). Além disso, eu estaria interessado em ler esse artigo, mas o link está quebrado.
Codcode 22/08/13
4 anos depois, você ainda está usando o jMockit como sua estrutura de teste principal? Estou testando pela primeira vez e encontrando alguns problemas com ele, mas não sei se sou eu quem não entende como o jMockit funciona ou se é um recurso que simplesmente não existe.
Eric B.
O jMockit não suporta mais o teste de métodos privados. A classe Deencapsulation foi preterida lentamente e removida totalmente na versão 1.47. jmockit.github.io/changes.html
Pytry
4

Para facilitar o teste de nossa base de código herdada (com muitas chamadas de método estáticas, etc.), o JMockit tem um valor inestimável. [Plug descarado para um artigo no meu blog]

Jeff Olson
fonte
0

Eu pessoalmente prefiro o EasyMock .
A capacidade de desviar entre controles legais, normais e rígidos de zombaria é um dos meus recursos favoritos.

Bivas
fonte