2015-10-20 4 views
2

Вот код модульного тестирования. Когда мы запускаем единичный тестовый код (SampleServiceTest2); EntityManager, введенный в AbstractDao, всегда равен нулю! Как мы можем вводить их во время модульного теста.EntityManager имеет значение null при модульном тестировании с помощью org.jglue.cdi-unit

*** 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. Внедрение entityManager с использованием @PersistenceContext в AbstractDAO не является частью автономного CDI, оно поддерживается только в том случае, если приложение работает на сервере приложений Java EE.

Решение заключается в том, чтобы внедрить EntityManager с использованием механизма CDI и создать производителя. Затем производитель может быть переключен на альтернативу в модульных тестах, чтобы предоставить тестовый 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(); 
    } 

} 

И это еще не достаточно. Вам необходимо создать новый тестовый ресурс persistence.xml в тестовом ресурсе с единицей проверки безопасности с именем «meopdb-test». Для этого устройства вам необходимо указать RESOURCE_LOCALtransaction-type и указать информацию о соединении. И последнее, что нельзя забыть - вам нужно перечислить все свои сущности в файле persistence.xml или во внешнем файле orm. Это связано с тем, что ваши тесты выполняются за пределами сервера приложений. Внутри сервера приложений JPA может автоматически находить объекты.

+0

Спасибо за помощь. – fatihn

+0

Если вы решите пойти на рамки аркиллианских тестов, инструмент [Forge tool] (http://forge.jboss.org/) с плагином для arquillian должен помочь вам настроить ваш тест либо из командной строки, либо из вашей IDE. – OndrejM

Смежные вопросы