Hi everyone,
I'm having a hard time finding a way to write unittests for my CDI enabled project using CdiTestRunner from Deltaspike
Test-Control. I'm trying a pretty basic setup, effectively consisting of these four classes:
1. A facade to retrieve Company entities (which are simple JPA entity beans):
@Default
@RequestScoped
public class CompanyFacade {
@Inject
private CompanyDAO _companyDao; // This is a deltaspike data DAO
@Transactional
public Company get(String id) {
return _companyDao.findBy(id);
}
@Transactional
public Company save(Company company) {
if (company.getCreateTimeStamp() == null) {
company.setCreateTimeStamp(new Date());
}
return _companyDao.save(company);
}
@Transactional
public SortableLazyList<Company> findAll() {
...
}
}
2. The DAO:
@Repository(forEntity=Company.class)
@Default
@Dependent
public interface CompanyDAO extends EntityRepository<Company, String>,
EntityManagerDelegate<Company> {
@Query(value = "select e from Company e")
public QueryResult<Company> findCompanies();
}
3. An Entity Manager Provider for the Tests, which uses a temporary H2
database, registered via beans.xml:
@Alternative
public class TestEntityManagerProducer {
@Produces
public EntityManager create() {
return
Persistence.createEntityManagerFactory("mamsTestCDI").createEntityManager();
}
public void close(@Disposes EntityManager em) {
if (em.isOpen()) {
em.close();
}
}
}
4. And the test class:
@RunWith(CdiTestRunner.class)
public class CompanyFacadeTest extends TestCase {
@Inject
private CompanyFacade _companyFacade;
@Test
public void generalTest() {
Company c;
c = new Company();
c.setKey(UUID.randomUUID().toString());
c.setName("A company");
c.setDescription("Such a company");
_companyFacade.save(c);
assertEquals(_companyFacade.findAll().size(), 1);
}
}
My Problems:
1.) The Test will not inject the CompanyFacade class. I'm trying with two different CDI implementations, Weld and
OpenEJB. Both say that they cannot find something to inject. Weld uses the infamous error "WELD-001408: Unsatisfied
dependencies". OpenEJB says "Api type [com.musicacademy.mams.facades.CompanyFacade] is not found with the qualifiers".
The only way that I can make this work is to a) Also add @Alternative to the CompanyFacade and b) add it to the
beans.xml (which will break this functionality on the live server, where everything is actually working as intended).
2.) But then I get a different error when saving the Company in the test, which effectively tells me that JTA is not
properly setup (as I think):
org.apache.deltaspike.data.api.QueryInvocationException: Failed calling Repository:
[Repository=com.musicacademy.mams.dao.CompanyDAO,entity=com.musicacademy.mams.data.Company,method=save,exception=class
javax.naming.NameNotFoundException,message=null
at
org.apache.deltaspike.data.impl.handler.QueryHandler.process(QueryHandler.java:134)
at
org.apache.deltaspike.data.impl.handler.QueryHandler.invoke(QueryHandler.java:108)
at
org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler.proceedOriginal(DelegateManualInvocationHandler.java:46)
at
org.apache.deltaspike.proxy.impl.invocation.AbstractManualInvocationHandler.invoke(AbstractManualInvocationHandler.java:63)
at
org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler.staticInvoke(DelegateManualInvocationHandler.java:39)
at com.musicacademy.mams.dao.CompanyDAO$$DSPartialBeanProxy.save(Unknown
Source)
at com.musicacademy.mams.facades.CompanyFacade.save(CompanyFacade.java:74)
...
Caused by: javax.naming.NameNotFoundException; remaining name
'TransactionSynchronizationRegistry'
at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:449)
at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:536)
at org.eclipse.jetty.jndi.NamingContext.lookup(NamingContext.java:551)
at
org.eclipse.jetty.jndi.java.javaRootURLContext.lookup(javaRootURLContext.java:117)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at org.apache.deltaspike.core.impl.util.JndiUtils.lookup(JndiUtils.java:96)
at
org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy.resolveTransactionRegistry(BeanManagedUserTransactionStrategy.java:195)
at
org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy$UserTransactionAdapter.<init>(BeanManagedUserTransactionStrategy.java:210)
at
org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy.getTransaction(BeanManagedUserTransactionStrategy.java:142)
at
org.apache.deltaspike.jpa.impl.transaction.ResourceLocalTransactionStrategy.rollbackAllTransactions(ResourceLocalTransactionStrategy.java:336)
at
org.apache.deltaspike.jpa.impl.transaction.ResourceLocalTransactionStrategy.execute(ResourceLocalTransactionStrategy.java:154)
at
org.apache.deltaspike.data.impl.tx.TransactionalQueryRunner.executeTransactional(TransactionalQueryRunner.java:72)
at
org.apache.deltaspike.data.impl.tx.TransactionalQueryRunner.executeQuery(TransactionalQueryRunner.java:54)
at
org.apache.deltaspike.data.impl.handler.QueryHandler.process(QueryHandler.java:122)
...
So I'm actually thinking that my CDI test environment is generally not really working. As I'm new to CDI I might be
missing something pretty basic, so any help is appreciated.
An extract from my Ivy dependencies for the tests:
<dependency org="org.apache.deltaspike.modules" name="deltaspike-test-control-module-api"
rev="&deltaspike.version;" conf="test->default"/>
<dependency org="org.apache.deltaspike.modules" name="deltaspike-test-control-module-impl"
rev="&deltaspike.version;" conf="test->default"/>
<dependency org="org.apache.deltaspike.cdictrl" name="deltaspike-cdictrl-openejb" rev="&deltaspike.version;"
conf="test->default"/>
<dependency org="org.apache.openejb" name="openejb-core" rev="4.7.2"
conf="test->default"/>
<dependency org="com.fasterxml" name="classmate" rev="1.3.1"
conf="test->default"/>
Kind regards,
Oliver Weise