Vraptor Mockito unit test (CDI)

Asked

Viewed 165 times

1

someone can give me a light, how to make the unit tests using Mockito next to the complete CDI of the Vraptor application?

I use CDI a lot to control my objects like automatic management of my dao together with the manager with @Inject.

More when using unit tests the same is not instantiating those my objects that should be injected automatically.

If I give a @Injectmocks on my Dao, beauty, plus the @inject within the Dao class that gets my Entitymanager does not work, and is not injected.

I then tried to do @Injectmocks on Entitymanager and instantiate my Dao class in hand by passing it, but without success. Apparently the Mock inject has no power to do this in Entitymanager.

Someone can give me a light?

Thank you.

1 answer

0


It is that it does not work as you think, when you are running the unit tests you are in a standalone context, everything should be done in a very manual way, eg: if you want to test your repositories (DAO’s) you could create a test suite where you have an abstract class that all your tests must extend, it will be responsible for creating the factory, create the entityManager, start a transaction, commit and then destroy the resources, this will run for each of the tests, testing everything in isolation, just so you know the detail, you want to test repositories (DAO’s) and this is no longer a unit test to be integration test, ex:

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.junit.AfterClass;
import org.junit.BeforeClass;

/**
 * Classe abstrata utilizada para testes, responsável por abrir conexão com
 * HSQLDB e encerrar os recursos após uso.
 *
 * @author Dilnei Cunha
 */
public abstract class AbstractRepositoryTest {

    protected static EntityManagerFactory emFactory;
    protected static EntityManager em;

    /**
     * Abrindo conexão com o Database, criando a EntityManager e abrindo a
     * transação.
     */
    @BeforeClass
    public static void setUp0() {
        emFactory = Persistence.createEntityManagerFactory("seu-ejbPU-test");
        em = emFactory.createEntityManager();
        em.getTransaction().begin();
    }

    /**
     * Comita a transação, encerra a EntityManager e a factory.
     */
    @AfterClass
    public static void tearDown0() {
        em.getTransaction().commit();
        em.close();
        emFactory.close();
    }
}

If you are used to developing tests, you know that you should use persistence.xml for the tests you get in

src test Resources META-INF persistemce.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1">
    <persistence-unit name="seu-ejbPU-test" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <class>br.com.suaApp.model.entity.SuaEntidade</class>
        .... suas classes 
        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbc.JDBCDriver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem:meubanco-test" />
            <property name="javax.persistence.jdbc.user" value="sa" />
            <property name="javax.persistence.jdbc.password" value="" />
            <property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

In my case for repository testing I usually use memory banks, so for each test I insert the records referring to the repository that will be tested, also note that in the action I use drop-and-create where every time I run the tests I destroy everything and create again, I don’t know if it uses containers Enterprise(full Javaee application servers) but notice that the transactinal type is RESOURCE_LOCAL and not JTA if applicable.

example of what a repository test would look like:

import org.junit.Before;
import org.junit.Test;

public class SeuObjetoRepositoryTest extends AbstractRepositoryTest {

    private SeuObjetoRepository repository;
    private SeuObjeto seuObjeto1;
    private SeuObjeto seuObjeto2;

        repository = new SeuObjectoRepository(em);

        seuObjeto1 = new SeuObjeto(1L, "Joao", "teste", "12345678987");
        seuObjeto1 = repository.salvar(seuObjeto1);
        em.refresh(seuObjeto1);

        seuObjeto2 = new SeuObjeto(2L, "Zeneida", "teste2", "12345678987");
        seuObjeto2 = repository.salvar(seuObjeto2);
        em.refresh(seuObjeto2);
       ....
    }

    @Test
    public void testBuscaListaSeusObjetos() {
        List<SeuObjeto> objetos = repository.buscarLista();
        assertThat(objetos, contains(seuObjeto2, seuObjeto1));
        assertThat(objetos, not(contains(seuObjeto2, seuObjeto1)));
    }

    @After
    public void tearDown() {
        repository.excluir(seuObjeto1);
        repository.excluir(seuObjeto2);
        ....destruir tudo no final da execução do teste.
    }
}

To test the services, you should use Mocks as you may already know, as your repositories have already been tested they should not be tested again, if your service uses the repository it should be mocked, e.g.:

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

/**
 * @author Dilnei Cunha
 */
public class SeuObjetoServiceBeanTest {

    private seuObjetoServiceLocal seuObjetoServiceBean;

    @Mock
    private SeuObjetoRepository seuObjetoRepository;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        seuObjetoServiceBean = new SeuObjetoServiceBean(seuObjetoRepository);
    }

    @Test
    public void testSuaLogicaDeNegociosDependedoOQueOServicoFaz() {

        when(seuObjetoDatabase).thenReturn(seuObjeto);
        ........
    }
        ......... demais testes
}

The other options for testing, if you want your tests to look like the actual application running with everything integrated, then you should use a test engine like the Arquillian, I use it is very powerful, even at the time of the tests I climb an Embedded container like Wildfly and I can test all injections and dependencies, but the way to program this changes, at first it may be a bit arduous to configure it, but it would already be subject to another post, I hope I helped you with something, hugging.

  • 1

    It was what I really had in mind, having to build everything in hand like Entityfactory and etc... so I didn’t think much so that directly what resources would be. But your post has really helped me understand how it works.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.