CDI Weld – Testes unitários

Esse post é uma continuação do post sobre injeção de dependência utilizando CDI weld.

Para quem costuma fazer tests unitários para as aplicações desenvolvidas, vou mostrar uma forma fácil de fazer isso utilizando CDI.

Se você utilizou o arquivo pom.xml que eu passei no primeiro post, viu que o projeto já possui a dependência do junit.

 
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.10</version>
		<scope>provided</scope>
	</dependency>

Antes de escrever o teste, precisamos criar um Junit Class Runner que irá prover as instâncias do objetos injetados na classe de test.

 
/**
 * @author wmews
 */
public class WeldJUnit4Runner extends BlockJUnit4ClassRunner {

	private final Class klass;
	private final Weld weld;
	private final WeldContainer container;

	public WeldJUnit4Runner(final Class klass) throws InitializationError {
		super(klass);
		this.klass = klass;
		this.weld = new Weld();
		this.container = weld.initialize();
	}

	@Override
	protected Object createTest() throws Exception {
		final Object test = container.instance().select(klass).get();
		return test;
	}
}

Depois de criado esta classe podemos criar o nosso teste. A classe de teste a ser criado precisa ser anotada com @RunWith(WeldJunit4Runner.class) e pronto. Segue um exemplo de test de movimentação em caixa eletrônico (exemplo criado no post anterior).

 
/**
 * @author wmews
 *
 */
@RunWith(WeldJUnit4Runner.class)
public class ATMTest {

	@Inject
	private ATM atm;
	@Inject
	private BankAccount bankAccount;

	@Test
	public void testInjections() {
		assertNotNull(atm);
		assertNotNull(bankAccount);
	}

	@Test
	public void testDeposit() {
		bankAccount.setBalance(0);
		atm.deposit(10);
		Assert.assertEquals(bankAccount.getBalance(), 10);
	}

	@Test
	public void testTake() {
		bankAccount.setBalance(10);
		atm.take(10);
		Assert.assertEquals(bankAccount.getBalance(), 0);
	}
}

O projeto completo está disponível no Github.

7 responses to “CDI Weld – Testes unitários

  1. Willian,
    implementei as classes conforme seu exemplo e, ao instanciar a classe WeldJUnit4Runner, devido a anotação RunWith, o valor do objeto klass passado para o construtor da mesma é a classe que foi anotada ao invés do objeto que deveria ser injetado. Fazendo uma analogia ao seu exemplo, é como se o klass chegasse no construtor do WeldJUnit4Runner com o valor ATMTest.class, ao invés de chegar como ATM.class ou BankAccount.class.
    Minha classe ficou assim:

    @RunWith(WeldJUnit4Runner.class)
    public class ColaboradorControllerTest {

    @Inject
    private ColaboradorController colaboradorController;

    /**
    * Testa se os objetos foram injetados.
    */
    @Test
    public void testInjections() {
    assertNotNull(this.colaboradorController);
    }
    }

    Você vê algo de errado nela?
    Agradeço a ajuda.

  2. Olá Vinicius.

    No seu caso você vai receber no construtor do WeldJUnit4Runner o ColaboradorControllerTest.

    O Weld faz com que a sua classe ColaboradorControllerTest, ao executar cada teste unitário, seja um objeto injetável contido no container. Isso lhe permite que ela possa injetar outras dependências, como o ATM e BankAccount.

    Essa sua dúvida é porque o exemplo não está funcionando?

  3. Entendi.
    Seguindo o que você falou, está funcionando corretamente, a classe que é passada para o construtor é a ColaboradorControllerTest, porém, na linha 19 da classe WeldJUnit4Runner ocorre uma exceção ao tentar recuperar uma instância de ColaboradorControllerTest, conforme abaixo:

    org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308 Unable to resolve any beans for Types: [class br.com.visasi.aplicativo.sicom.presentation.controller.ColaboradorControllerTest]; Bindings: [QualifierInstance{annotationClass=interface javax.enterprise.inject.Any, values={}, hashCode=1625223146}]
    at org.jboss.weld.manager.BeanManagerImpl.getBean(BeanManagerImpl.java:699)
    at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:102)
    at br.com.visasi.aplicativo.sisom.test.util.WeldJUnit4Runner.createTest(WeldJUnit4Runner.java:23)
    at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:258)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:255)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

  4. Estava com o pacote errado na exceção, mas o erro continua mesmo corrigindo. Estava br.com.visasi.aplicativo.sisom, quando deveria ser br.com.visasi.aplicativo.sicom.

  5. Vinícius, provavelmente você esqueceu do beans.xml dentro do META-INF do seu projeto. []’s

  6. Cara não consegui fazer fica dando erro, tem como você disponibilizar o código no github, por favor.

  7. É. Testei também e sempre ocorre o mesmo erro. No meu caso meu ambiente tem o beans.xml no WEB-INF, pois não é EE. Mas mesmo copiando para o META-INF não funcionou.

Leave a Reply

Your email address will not be published. Required fields are marked *