Pergunta

Qual é a melhor estrutura para criar objetos simulados em Java?Por que?Quais são os prós e os contras de cada estrutura?

Foi útil?

Solução

Eu tive um bom sucesso usando Mockito.

Quando tentei aprender sobre JMock e EasyMock, achei a curva de aprendizado um pouco íngreme (embora talvez seja só eu).

Gosto do Mockito por causa de sua sintaxe simples e limpa que consegui entender rapidamente.A sintaxe mínima foi projetada para suportar muito bem os casos comuns, embora nas poucas vezes em que precisei fazer algo mais complicado, descobri que o que queria era suportado e fácil de entender.

Aqui está um exemplo (resumido) da página inicial do Mockito:

import static org.mockito.Mockito.*;

List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();

Não pode ser muito mais simples do que isso.

A única grande desvantagem que consigo pensar é que ele não zomba de métodos estáticos.

Outras dicas

Eu sou o criador do PowerMock, então obviamente devo recomendá-lo!:-)

PowerMock estende EasyMock e Mockito com a capacidade de simular métodos estáticos, métodos finais e até privados.O suporte do EasyMock está completo, mas o plugin Mockito precisa de mais trabalho.Estamos planejando adicionar suporte JMock também.

O PowerMock não se destina a substituir outros frameworks, mas pode ser usado em situações complicadas quando outros frameworks não permitem zombaria.PowerMock também contém outros recursos úteis, como suprimindo inicializadores estáticos e construtores.

O Site do projeto JMockit contém muitas informações comparativas para os kits de ferramentas de simulação atuais.

Em especial, confira o matriz de comparação de recursos, que abrange EasyMock, jMock, Mockito, Unitils Mock, PowerMock e, claro, JMockit.Tento mantê-lo preciso e atualizado, tanto quanto possível.

Tenho tido sucesso com JMockit.

É muito novo e, portanto, um pouco cru e pouco documentado.Ele usa ASM para redefinir dinamicamente o bytecode da classe, para que possa simular todos os métodos, incluindo estáticos, privados, construtores e inicializadores estáticos.Por exemplo:

import mockit.Mockit;

...
Mockit.redefineMethods(MyClassWithStaticInit.class,
                       MyReplacementClass.class);
...
class MyReplacementClass {
  public void $init() {...} // replace default constructor
  public static void $clinit{...} // replace static initializer
  public static void myStatic{...} // replace static method
  // etc...
}

Possui uma interface Expectations que permite também cenários de gravação/reprodução:

import mockit.Expectations;
import org.testng.annotations.Test;

public class ExpecationsTest {
  private MyClass obj;

  @Test
  public void testFoo() {
    new Expectations(true) {
      MyClass c;
      {
        obj = c;
        invokeReturning(c.getFoo("foo", false), "bas");
      }
    };

    assert "bas".equals(obj.getFoo("foo", false));

    Expectations.assertSatisfied();
  }

  public static class MyClass {
    public String getFoo(String str, boolean bool) {
      if (bool) {
        return "foo";
      } else {
        return "bar";
      }
    }
  }
}

A desvantagem é que requer Java 5/6.

Você também pode dar uma olhada nos testes usando Groovy.No Groovy você pode facilmente simular interfaces Java usando o operador 'as':

def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest 

Além dessa funcionalidade básica, o Groovy oferece muito mais em termos de simulação, incluindo o poderoso MockFor e StubFor Aulas.

http://docs.codehaus.org/display/GROOVY/Groovy+Mocks

Comecei a usar mocks com EasyMock.Fácil de entender, mas a etapa de repetição foi meio chata. Mockito remove isso, também possui uma sintaxe mais limpa, pois parece que a legibilidade era um de seus principais objetivos.Não consigo enfatizar o suficiente o quão importante isso é, já que a maioria dos desenvolvedores gastará seu tempo lendo e mantendo o código existente, e não criando-o.

Outra coisa interessante é que as interfaces e classes de implementação são tratadas da mesma maneira, ao contrário do EasyMock, onde você ainda precisa lembrar (e verificar) para usar uma extensão de classe EasyMock.

Eu dei uma olhada rápida JMockit recentemente, e embora a longa lista de recursos seja bastante abrangente, acho que o preço disso é a legibilidade do código resultante e a necessidade de escrever mais.

Para mim, Mockito atinge o ponto ideal, sendo fácil de escrever e ler e lidar com a maioria das situações que a maioria dos códigos exigirá.Usando Mockito com PowerMock seria minha escolha.

Uma coisa a considerar é que a ferramenta que você escolheria se estivesse desenvolvendo sozinho ou em uma equipe pequena e unida, pode não ser a melhor opção para uma grande empresa com desenvolvedores de diversos níveis de habilidade.A legibilidade, a facilidade de utilização e a simplicidade necessitariam de mais consideração neste último caso.Não faz sentido obter o framework de simulação definitivo se muitas pessoas acabam não o usando ou não mantendo os testes.

Estamos usando fortemente EasyMock e EasyMock Class Extension em funcionamento e estou muito feliz com isso.Basicamente, oferece tudo o que você precisa.Dê uma olhada na documentação, tem um exemplo muito legal que mostra todas as funcionalidades do EasyMock.

Eu usei JMock cedo.Experimentei o Mockito no meu último projeto e gostei.Mais conciso, mais limpo.PowerMock cobre todas as necessidades que estão ausentes no Mockito, como simular um código estático, simular a criação de uma instância, simular classes e métodos finais.Então tenho tudo que preciso para realizar meu trabalho.

Gosto do JMock porque você é capaz de criar expectativas.Isso é totalmente diferente de verificar se um método foi chamado e encontrado em algumas bibliotecas simuladas.Usando JMock você pode escrever expectativas muito sofisticadas.Veja o jmock trapaça.

Sim, Mockito é um ótimo framework.Eu uso junto com isquiotibial e Guia do Google para configurar meus testes.

A melhor solução para zombar é fazer com que a máquina faça todo o trabalho com testes automatizados baseados em especificações.Para Java, consulte ScalaCheck e a Redução quadro incluído no Java Funcional biblioteca.Com estruturas de teste automatizadas baseadas em especificações, você fornece uma especificação do método em teste (uma propriedade sobre ele que deve ser verdadeira) e a estrutura gera testes, bem como objetos simulados, automaticamente.

Por exemplo, a propriedade a seguir testa o método Math.sqrt para ver se a raiz quadrada de qualquer número positivo n ao quadrado é igual a n.

val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }

Quando Você ligar propSqrt.check(), ScalaCheck gera centenas de números inteiros e verifica sua propriedade para cada um, garantindo também automaticamente que os casos extremos sejam bem cobertos.

Embora ScalaCheck seja escrito em Scala e exija o compilador Scala, é fácil testar o código Java com ele.A estrutura Reductio em Functional Java é uma implementação Java pura dos mesmos conceitos.

Mockito também oferece a opção de métodos stubbing, correspondência de argumentos (como anyInt() e anyString()), verificação do número de invocações (times(3), atLeastOnce(), never()), e mais.

Eu também descobri que Mockito é simples e limpo.

Uma coisa que não gosto no Mockito é que você não é possível fazer stub de métodos estáticos.

Para algo um pouco diferente, você poderia usar JRuby e Mocha que são combinados em JtestR para escrever testes para seu código Java em Ruby expressivo e sucinto.Existem alguns exemplos úteis de simulação com JtestR aqui.Uma vantagem dessa abordagem é que zombar de classes concretas é muito simples.

Comecei a usar mocks por meio do JMock, mas acabei fazendo a transição para usar o EasyMock.EasyMock era exatamente isso, --mais fácil-- e fornecia uma sintaxe que parecia mais natural.Não mudei desde então.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top