本文介绍了在CDI-Unit中注入@PersistenceContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是单元测试代码.当我们运行单元测试代码(SampleServiceTest2)时;在AbstractDao中注入的EntityManager始终为null!我们如何在单元测试期间注入em.

Here is the unit testing code. When we run unit test code (SampleServiceTest2); EntityManager injected in AbstractDao is always null! How can we inject em during unit test.

*** SampleServiceTest2.java

*** SampleServiceTest2.java

import javax.inject.Inject;

import org.jglue.cdiunit.CdiRunner;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(CdiRunner.class)
public class SampleServiceTest2 {

    @Inject SampleService greeter;

    @Test
    public void testGreeter() throws Exception {
        System.out.println("before2");
        greeter.addSampleData(new SampleDataDto(), new KullaniciDto());
        System.out.println("after2");
    }
}

*** SampleService.java

*** SampleService.java

import javax.ejb.Stateless;
import javax.inject.Inject;
....

@Stateless
@SecuredBean
public class SampleService {

    @Inject
    SampleLogic sampleLogic;

    @Yetki(tag="perm_add_sample_data")
    public void addSampleData(SampleDataDto data, KullaniciDto aktifKullaniciDto){
        SampleDataHelper sampleDataHelper = new SampleDataHelper();

        SampleData sampleData = sampleDataHelper.getEntity(data);
        KullaniciHelper kullaniciHelper = new KullaniciHelper();

        Kullanici kullanici = kullaniciHelper.getEntity(aktifKullaniciDto);
        sampleLogic.addData(sampleData, kullanici);
    }

}

**** SampleLogic.java

**** SampleLogic.java

import javax.inject.Inject;

....

public class SampleLogic {
    @Inject
    SampleDataDao sampleDataDao;

    public void addData(SampleData data, Kullanici kullanici) {
        addData1(data,kullanici);
        System.out.println("SampleLogic : addData() called!");
    }

    public void addData1(SampleData data, Kullanici kullanici) {
        sampleDataDao.create(data, kullanici);
    }
}

**** SampleDataDao.java

**** SampleDataDao.java

public class SampleDataDao extends AbstractDao<SampleData> {
    private static final long serialVersionUID = 1L;
}

**** AbstractDao.java

**** AbstractDao.java

public abstract class AbstractDao<T extends BaseEntity> implements Serializable {

    private static final long serialVersionUID = 1L;

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

    protected EntityManager getEm() {
        return em;
    }

    @SuppressWarnings("rawtypes")
    private Class entityClass;


    @SuppressWarnings("rawtypes")
    private Class getEntityClass() {
        if (entityClass == null) {
            entityClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        }
        return entityClass;
    }

    public T create(T t, Kullanici kullanici) {
        if (t.getId() != null) {
            throw new IllegalStateException("Create Operation: Oid should be null");
        }
        t.setId(getSeqNextValue(t));
        t.setEklemeZamani(new Timestamp(Calendar.getInstance().getTimeInMillis()));
        t.setEkleyenKullaniciId(kullanici.getId());

        t.setDurumId(EnumDurum.AKTIF.getValue());

        t = em.merge(t);
        em.flush();
        return t;
    }
}

推荐答案

如果使用CDIUnit进行测试,则唯一获得的就是CDI注入,而不是Java EE的全部功能.使用@PersistenceContext将注入到AbstractDAO中不是独立CDI的一部分,仅当应用程序在Java EE应用程序服务器中运行时才受支持.

If you test with CDIUnit, the only thing you get is CDI injections, not the full power of Java EE. Injecting entityManager using @PersistenceContext into AbstractDAO is not part of standalone CDI, it is only supported when application is running within a Java EE application server.

解决方案是使用CDI机制注入EntityManager并创建一个生产者.然后可以将生产者切换为单元测试中的替代方案,以提供测试EntityManager.但是,在独立的单元测试中设置JPA并不是那么简单,因为您需要直接在persistence.xml文件中指定连接属性.另外,不要忘记在测试依赖项中添加JPA实现的依赖项(休眠,eclipselink).

The solution is to inject EntityManager using CDI mechanism and create a producer. The producer could be then switched for an alternative in unit tests to provide test entityManager. However, setting up JPA in a standalone unit test is not so straightforward, as you need to specify connection properties directly in persistence.xml file. Also, do not forget to add dependencies on a JPA implementation (hibernate, eclipselink) into your test dependencies.

但是,如果您不想修改应用程序的代码,或者在测试中需要的不仅仅是CDI,则应该查看 Arquillian Java EE测试框架.

However, if you do not want to adapt your application's code or you need more than CDI in your tests, you should have a look at Arquillian Java EE test framework.

以下是CDIUnit的示例:

Here is an example for CDIUnit:

public abstract class AbstractDao<T extends BaseEntity> implements Serializable {
...
    @Inject
    @Named("meopdb")
    private EntityManager em;
...
}

// producer in application - just a wraper over `@PersisteneContext`
public class EntityManagerProducer {
    @Produces
    @PersistenceContext(unitName="meopdb")
    @Named("meopdb")
    private EntityManager em;
}

/* producer in your test sources - it creates entityManager via API calls instead of injecting via `@PersistenceContext`. Also, a different persistence unit is used so that it does not clash with main persistence unit, which requires datasource from app server
*/
public TestEntityManagerProducer {
    @Produces
    @ProducesAlternative // CDIUnit annotation to turn this on as an alternative automatically
    @Named("meopdb")
    public EntityManager getEm() {
        return Persistence
                .createEntityManagerFactory("meopdb-test")
                .createEntityManager();
    }

}

还不够.您需要在测试资源中使用名为"meopdb-test"的测试持久性单元创建一个新的persistence.xml.对于本机,您需要指定RESOURCE_LOCAL transaction-type,并指定连接信息.最后一件事不要忘记-您需要在persistence.xml或外部orm文件中列出所有实体.这是因为您的测试在应用程序服务器之外运行.在应用服务器内部,JPA可以自动查找实体.

And it is not yet enough. You need to create a new persistence.xml in your test resources with the test persistence unit named "meopdb-test". For this unit you need to specify RESOURCE_LOCAL transaction-type, and specify connection information. And last thing not to forget - you need to list all your entities in the persistence.xml, or in external orm file. This is because your tests run outside of application server. Inside app server, JPA can find entities automatically.

这篇关于在CDI-Unit中注入@PersistenceContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 14:22