2015-10-20 81 views
2

以下是單元測試代碼。當我們運行單元測試代碼(SampleServiceTest2)時;在AbstractDao中注入的EntityManager始終爲空!我們如何在單元測試期間注入em。使用org.jglue.cdi-unit進行單元測試時,EntityManager爲null

*** 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

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

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

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

**** 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; 
    } 
} 

回答

5

如果用CDIUnit測試,你得到的僅僅是CDI注射,而不是Java EE的全部功能。使用@PersistenceContext注入到AbstractDAO中的entityManager不是獨立CDI的一部分,它僅在應用程序在Java EE應用程序服務器中運行時受支持。

解決方案是使用CDI機制注入EntityManager並創建生產者。然後生產者可以在單元測試中交換替代,以提供測試entityManager。但是,在獨立單元測試中設置JPA並不那麼直接,因爲您需要直接在persistence.xml文件中指定連接屬性。另外,不要忘記將JPA實現(hibernate,eclipselink)的依賴添加到測試依賴項中。但是,如果您不想調整應用程序的代碼,或者在測試中需要的不僅僅是CDI,還應該查看Arquillian Java EE test framework

下面是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_LOCALtransaction-type,並指定連接信息。最後不要忘記 - 你需要將所有實體列在persistence.xml或外部orm文件中。這是因爲您的測試運行在應用程序服務器之外。在應用服務器內部,JPA可以自動查找實體。

+0

感謝您的幫助。 – fatihn

+0

如果您選擇使用arquillian測試框架,使用arquillian插件的[Forge工具](http://forge.jboss.org/)應該可以幫助您通過命令行或IDE設置您的測試。 – OndrejM

相關問題