= Compositor de Aplicações
:index-group: Testing Techniques
:jbake-type: page
:jbake-status: published

O `org.apache.openejb.junit.ApplicationComposer` é o executor de testes JUnit modelado de acordo com a forma como fizemos testes internos no OpenEJB por anos (desde 2006).
Isto não envolve o escaneamento de toda a classpath.  Se você quiser alguma coisa na aplicação, você deve construí-lo diretamente no seu testcase.

Com o `ApplicationComposer` você pode fazer testes idênticos ao que o OpenEJB usa internamente, mas com dependência limitada do próprio OpenEJB.  A principal dependência está no código
que é usado para construir as aplicações atuais:

    <dependency>
      <groupId>org.apache.tomee</groupId>
      <artifactId>openejb-core</artifactId>
      <version>${openejb.version}</version>
    </dependency>

== Compondo um aplicativo

A principal diferença para a API incorporada `EJBContainer` é construir o aplicativo no código de teste. Isso é feito com um ou mais métodos no caso de teste anotado
com `org.apache.openejb.testing.Module` usando o seguinte formato:

    @Module
    public <return-value> <module-name>() {

onde **module-name** é o nome que você deseja usar para esse módulo e **return-value** pode ser qualquer um dos deles:

 - java.lang.Class
 - java.lang.Class[]
 - org.apache.openejb.jee.EjbJar
 - org.apache.openejb.jee.EnterpriseBean
 - org.apache.openejb.jee.Application
 - org.apache.openejb.jee.Connector
 - org.apache.openejb.jee.Beans
 - org.apache.openejb.jee.jpa.unit.Persistence
 - org.apache.openejb.jee.jpa.unit.PersistenceUnit

== Exemplo

Usado em um testcase atual, pode ser assim:
[source,java,numbered]
----
    import junit.framework.TestCase;
    import org.apache.openejb.jee.EjbJar;
    import org.apache.openejb.jee.StatefulBean;
    import org.apache.openejb.jee.jpa.unit.PersistenceUnit;
    import org.apache.openejb.junit.ApplicationComposer;
    import org.apache.openejb.testing.Configuration;
    import org.apache.openejb.testing.Module;
    import org.junit.Test;
    import org.junit.runner.RunWith;

    import javax.annotation.Resource;
    import javax.ejb.EJB;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.transaction.UserTransaction;
    import java.util.List;
    import java.util.Properties;

    @RunWith(ApplicationComposer.class)
    public class MoviesTest extends TestCase {

        @EJB
        private Movies movies;

        @Resource
        private UserTransaction userTransaction;

        @PersistenceContext
        private EntityManager entityManager;

        @Module
        public PersistenceUnit persistence() {
            PersistenceUnit unit = new PersistenceUnit("movie-unit");
            unit.setJtaDataSource("movieDatabase");
            unit.setNonJtaDataSource("movieDatabaseUnmanaged");
            unit.getClazz().add(Movie.class.getName());
            unit.setProperty("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)");
            return unit;
        }

        @Module
        public EjbJar beans() {
            EjbJar ejbJar = new EjbJar("movie-beans");
            ejbJar.addEnterpriseBean(new StatefulBean(MoviesImpl.class));
            return ejbJar;
        }

        @Configuration
        public Properties config() throws Exception {
            Properties p = new Properties();
            p.put("movieDatabase", "new://Resource?type=DataSource");
            p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
            p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
            return p;
        }

        @Test
        public void test() throws Exception {

            userTransaction.begin();

            try {
                entityManager.persist(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
                entityManager.persist(new Movie("Joel Coen", "Fargo", 1996));
                entityManager.persist(new Movie("Joel Coen", "The Big Lebowski", 1998));

                List<Movie> list = movies.getMovies();
                assertEquals("List.size()", 3, list.size());

                for (Movie movie : list) {
                    movies.deleteMovie(movie);
                }

                assertEquals("Movies.getMovies()", 0, movies.getMovies().size());

            } finally {
                userTransaction.commit();
            }
        }
    }
----

== Executando
```
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running org.superbiz.composed.MoviesTest
    INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
    INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
    INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
    INFO - Configuring enterprise application: /Users/dblevins/examples/application-composer/MoviesTest
    WARN - Method 'lookup' is not available for 'javax.annotation.Resource'. Probably using an older Runtime.
    INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
    INFO - Auto-creating a container for bean org.superbiz.composed.MoviesTest: Container(type=MANAGED, id=Default Managed Container)
    INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
    INFO - Auto-creating a container for bean MoviesImpl: Container(type=STATEFUL, id=Default Stateful Container)
    INFO - Configuring PersistenceUnit(name=movie-unit)
    INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'.
    INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase)
    INFO - Adjusting PersistenceUnit movie-unit <non-jta-data-source> to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged'
    INFO - Enterprise application "/Users/dblevins/examples/application-composer/MoviesTest" loaded.
    INFO - Assembling app: /Users/dblevins/examples/application-composer/MoviesTest
    INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 449ms
    INFO - Jndi(name=org.superbiz.composed.MoviesTestLocalBean) --> Ejb(deployment-id=org.superbiz.composed.MoviesTest)
    INFO - Jndi(name=global/MoviesTest/EjbModule2027711095/MoviesTest!org.superbiz.composed.MoviesTest) --> Ejb(deployment-id=org.superbiz.composed.MoviesTest)
    INFO - Jndi(name=global/MoviesTest/EjbModule2027711095/MoviesTest) --> Ejb(deployment-id=org.superbiz.composed.MoviesTest)
    INFO - Jndi(name=MoviesImplLocal) --> Ejb(deployment-id=MoviesImpl)
    INFO - Jndi(name=global/MoviesTest/movie-beans/MoviesImpl!org.superbiz.composed.Movies) --> Ejb(deployment-id=MoviesImpl)
    INFO - Jndi(name=global/MoviesTest/movie-beans/MoviesImpl) --> Ejb(deployment-id=MoviesImpl)
    INFO - Created Ejb(deployment-id=org.superbiz.composed.MoviesTest, ejb-name=MoviesTest, container=Default Managed Container)
    INFO - Created Ejb(deployment-id=MoviesImpl, ejb-name=MoviesImpl, container=Default Stateful Container)
    INFO - Started Ejb(deployment-id=org.superbiz.composed.MoviesTest, ejb-name=MoviesTest, container=Default Managed Container)
    INFO - Started Ejb(deployment-id=MoviesImpl, ejb-name=MoviesImpl, container=Default Stateful Container)
    INFO - Deployed Application(path=/Users/dblevins/examples/application-composer/MoviesTest)
    INFO - Undeploying app: /Users/dblevins/examples/application-composer/MoviesTest
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.221 sec

    Results :

    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
```
