使用org.jglue.cdi-unit进行单元测试时,EntityManager为null [英] EntityManager is null when unit testing with org.jglue.cdi-unit

查看:249
本文介绍了使用org.jglue.cdi-unit进行单元测试时,EntityManager为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是单元测试代码。当我们运行单元测试代码(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 将entityManager注入 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并创建生产者。然后可以在单元测试中切换生产者以提供测试实体管理器。但是,在独立单元测试中设置JPA并不是那么简单,因为您需要直接在persistence.xml文件中指定连接属性。另外,不要忘记将JPA实现(hibernate,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.

这篇关于使用org.jglue.cdi-unit进行单元测试时,EntityManager为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆