Introdução ao teste com o Arquillian

Introdução ao teste com o Arquillian

1. Visão geral

Arquillian é uma estrutura de teste de integração independente de contêiner para Java EE. O uso do Arquillian minimiza a carga de gerenciamento de contêineres, implantações, inicializações de estrutura e assim por diante.

Podemos nos concentrar em escrever testes reais e não em inicializar o ambiente de teste.

2. Conceitos principais

2.1. Arquivos de implantação

Existe uma maneira fácil de testar nosso aplicativo ao executar dentro de um contêiner.

Em primeiro lugar, a classeShrinkWrap fornece uma API para criar arquivos*.jar,*.war,e*.ear implantáveis.

Então, o Arquillian nos permite configurar a implantação do teste usando a anotação@Deployment - em um método que retorna um objetoShrinkWrap.

2.2. Containers

Arquillian distingue três tipos diferentes de contêineres:

  • Remoto - testado usando um protocolo remoto como o JMX

  • Gerenciado - contêineres remotos, mas seu ciclo de vida é gerenciado pelo Arquillian

  • Embarcado - contêineres locais onde os testes são realizados usando protocolos locais

Além disso, podemos classificar contêineres por seus recursos:

  • Aplicativos Java EE implementados em um servidor de aplicativos como Glassfish ou JBoss

  • Contêineres de servlet implementados no Tomcat ou Jetty

  • Contêineres autônomos

  • Contêineres OSGI

Ele examina o caminho de classe do tempo de execução e seleciona automaticamente o contêiner disponível.

2.3. Enriquecimento de Teste

O Arquillian enriquece os testes fornecendo, por exemplo, a injeção de dependência para que possamos escrever nossos testes facilmente.

Podemos injetar dependências usando@Inject, injetar recursos com@Resource, beans de sessão EJB usando@EJB, etc.

2.4. Vários executores de teste

Podemos criar várias implantações usando a anotação:

@Deployment(name="myname" order = 1)

Onde o nome é o nome do arquivo de implantação e o parâmetro order é a ordem de execução da implantação, agora podemos executar testes em várias implantações ao mesmo tempo usando a anotação:

@Test @OperateOnDeployment("myname")

O teste anterior é executado no contêiner de implantaçãomyname usando a ordem definida na anotação@Deployment.

2.5. Extensões Arquillian

O Arquillian oferece várias extensões caso nossas necessidades de teste não sejam atendidas pelo tempo de execução do núcleo. Temos persistência, transações, cliente / servidor, extensões REST, etc.

Podemos ativar essas extensões adicionando dependências apropriadas aos arquivos de configuração do Maven ou Gradle.

As extensões mais usadas são Drone, Grafeno e Selênio.

3. Dependências e configuração do Maven

Vamos adicionar a seguinte dependência ao nosso arquivopom.xml:


    org.jboss.arquillian
    arquillian-bom
    1.1.13.Final
    import
    pom


    org.glassfish.main.extras
    glassfish-embedded-all
    4.1.2
    test


    org.jboss.arquillian.container
    arquillian-glassfish-embedded-3.1
    1.0.0.Final
    test

A versão mais recente das dependências pode ser encontrada aqui:arquillian-bom,org.glassfish.main.extras,org.jboss.arquillian.container.

4. Teste simples

4.1. Crie um componente

Vamos começar com um componente simples. Não incluímos nenhuma lógica avançada aqui para poder focar nos testes:

public class Component {
    public void sendMessage(PrintStream to, String msg) {
        to.println(message(msg));
    }

    public String message(String msg) {
        return "Message, " + msg;
    }
}

Usando o Arquillian, queremos testar se essa classe se comporta corretamente quando invocada como um bean CDI.

4.2. Escreva nosso primeiro teste de Arquillian

Primeiro, precisamos especificar que nossa classe de teste deve ser executada usando o corredor específico da estrutura:

@RunWith(Arquillian.class)

Se vamos executar nossos testes dentro de um contêiner, precisamos usar a anotação@Deployment.

O Arquillian não usa o caminho de classe inteiro para isolar o arquivo de teste. Em vez disso, ele usa a classeShrinkWrap, que é uma API Java para criar arquivos. Quando criamos o arquivo morto para teste, especificamos quais arquivos incluir no caminho de classe para usar o teste. Durante a implantação,ShrinkWrap isola apenas as classes necessárias para o teste.

Usando o métodoaddclass(), podemos especificar todas as classes necessárias e também adicionar um recurso de manifesto vazio.

OJavaArchive.class cria um arquivo da web mockup chamadotest.war, este arquivo é implantado no contêiner e então é usado pelo Arquillian para realizar testes:

@Deployment
public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addClass(Component.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}

Em seguida, injetamos nosso componente no teste:

@Inject
private Component component;

Por fim, realizamos nosso teste:

assertEquals("Message, MESSAGE",component.message(("MESSAGE")));

component.sendMessage(System.out, "MESSAGE");

5. Testando Enterprise Java Beans

5.1. Enterprise Java Bean

Com o Arquillian, podemos testar a injeção de dependência de um Enterprise Java Bean, para isso, criamos uma classe que possui um método para converter qualquer palavra em minúscula:

public class ConvertToLowerCase {
    public String convert(String word){
        return word.toLowerCase();
    }
}

Usando essa classe, criamos uma classe sem estado para chamar o método criado antes:

@Stateless
public class CapsConvertor {
    public ConvertToLowerCase getLowerCase(){
        return new ConvertToLowerCase();
    }
}

A classeCapsConvertor é injetada em um bean de serviço:

@Stateless
public class CapsService {

    @Inject
    private CapsConvertor capsConvertor;

    public String getConvertedCaps(final String word){
        return capsConvertor.getLowerCase().convert(word);
    }
}

5.2. Teste o Enterprise Java Bean

Agora podemos usar o Arquillian para testar nosso Java Bean corporativo, injetando oCapsService:

@Inject
private CapsService capsService;

@Test
public void givenWord_WhenUppercase_ThenLowercase(){
    assertTrue("capitalize".equals(capsService.getConvertedCaps("CAPITALIZE")));
    assertEquals("capitalize", capsService.getConvertedCaps("CAPITALIZE"));
}

UsandoShrinkWrap,, garantimos que todas as classes estão conectadas corretamente:

@Deployment
public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addClasses(CapsService.class, CapsConvertor.class, ConvertToLowerCase.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}

6. Testando JPA

6.1. Persistência

Também podemos usar o Arquillian para testar a persistência. Primeiro, vamos criar nossa entidade:

@Entity
public class Car {

    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    private String name;

    // getters and setters
}

Temos uma tabela que contém nomes de carros.

Em seguida, criaremos nosso EJB para executar operações básicas em nossos dados:

@Stateless
public class CarEJB {

    @PersistenceContext(unitName = "defaultPersistenceUnit")
    private EntityManager em;

    public Car saveCar(Car car) {
        em.persist(car);
        return car;
    }

    public List findAllCars() {
    Query query
      = em.createQuery("SELECT b FROM Car b ORDER BY b.name ASC");
    List entries = query.getResultList();

    return entries == null ? new ArrayList<>() : entries;

    public void deleteCar(Car car) {
        car = em.merge(car);
        em.remove(car);
    }
}

ComsaveCar, podemos salvar os nomes dos carros no banco de dados, podemos obter todos os carros armazenados comfindAllCars,e também podemos excluir um carro do banco de dados comdeleteCar.

6.2. Teste de persistência com Arquillian

Agora podemos realizar alguns testes básicos usando o Arquillian.

Primeiro, adicionamos nossas classes ao nossoShrinkWrap:

.addClasses(Car.class, CarEJB.class)
.addAsResource("META-INF/persistence.xml")

Então criamos nosso teste:

@Test
public void testCars() {
    assertTrue(carEJB.findAllCars().isEmpty());
    Car c1 = new Car();
    c1.setName("Impala");
    Car c2 = new Car();
    c2.setName("Lincoln");
    carEJB.saveCar(c1);
    carEJB.saveCar(c2);

    assertEquals(2, carEJB.findAllCars().size());

    carEJB.deleteCar(c1);

    assertEquals(1, carEJB.findAllCars().size());
}

Neste teste, primeiro criamos quatro instâncias de carro e verificamos se o número de linhas no banco de dados é o mesmo que criamos.

8. Conclusão

Neste tutorial, nós:

  • introduziu os conceitos centrais do Arquillian

  • injetou um componente no teste Arquillian

  • testou um EJB

  • persistência testada

  • realizou o teste Arquillian usando Maven

Você pode encontrar o código no artigoover on Github.