views:

581

answers:

2

Hi I came from the Spring camp , I don't want to use Spring , and am migrating to JavaEE6 , But I have problem testing DAO + JPA , here is my simplified sample :

public interface PersonDao
{
  public Person get(long id);
}

This is a very basic DAO , because I came from Spring , I believe DAO still has its value , so I decided to add a DAO layer .

public class PersonDaoImpl implements PersonDao , Serializable
{
  @PersistenceContext(unitName = "test", type = PersistenceContextType.EXTENDED)
  EntityManager entityManager ;

  public PersonDaoImpl()
  {
  }

  @Override
  public Person get(long id)
  {
    return entityManager .find(Person.class , id);
  }
}

This is a JPA-implemented DAO , I hope the EE container or the test container able to inject the EntityManager (just like Spring does).

public class PersonDaoImplTest extends TestCase
{
  @Inject 
  protected PersonDao personDao;

  @Override
  protected void setUp() throws Exception
  {
    //personDao = new PersonDaoImpl();
  }

  public void testGet()
  {
    System.out.println("personDao = " + personDao); // NULL !
    Person p = personDao.get(1L);
    System.out.println("p = " + p);
  }
}

This is my test file .

OK , here comes the problem : Because JUnit doesn't understand @javax.inject.Inject , the PersonDao will not be able to injected , the test will fail.

How do I find a test framework that able to inject the EntityManager to the PersonDaoImpl , and @Inject the PersonDaoImpl to the PersonDao of TestCase ?

I tried unitils.org , but cannot find a sample like this , it just directly inject the EntityManagerFactory to the TestCast , not what I want ...

+2  A: 

because I came from Spring, I believe DAO still has its value, so I decided to add a DAO layer.

I don't really see what Spring has to do with this. And I don't agree as I wrote in a previous answer. To me, JPA is a DAL (data access layer), and I don't see the point of putting a data access layer on top of another data access layer. At least not systematically. But let's not discuss this.

This is a JPA-implemented DAO , I hope the EE container or the test container able to inject the EntityManager (just like Spring does).

If your DAO is a managed component like a CDI managed bean, then the Java EE container should be able to inject an EntityManager in it.

For unit testing of container-managed objects, you don't need any kind of container. For integration testing, you will need some kind of container, just like you do for Spring beans, Hibernate/JPA entities, session beans, CDI managed beans or any other kind of container-managed object. You could use the EJB3.1 embeddable API in your tests. Also have a look at Arquillian.

Pascal Thivent
As to whether JPA has killed the DAO, it depends. At some points you would like to refactor the JPA code somewhere so that you can reuse it someplace else. What is then a better place than a DAO?
BalusC
@BalusC I don't agree with "use DAO systematically", I agree with "it depends" though... but not exactly for the reason you gave (I'm not saying you're wrong but I'd like to see a concrete illustration of your example, I have some difficulties at visualizing it).
Pascal Thivent
None yet, I haven't used JPA in real world projects yet, just hobbying it. But I can imagine that whenever you need to repeat the same bunch of JPA code lines, you'd like to refactor that away if it grows over 3~5 lines of code or so, and I yet can't imagine the "right" place to put those lines in. Is it a DAO class?
BalusC
A: 

You could also add method PersonDaoImpl.setEntityManager(EntityManager em), then set it by Persistence.createEntityManagerFactory("test").createEntityManager(). It's nothing with jee container.

卢声远 Shengyuan Lu