2012-05-28 63 views
5

我有一个使用JUnit做一些测试套件的生命周期问题。JUnit生命周期

为了写得心应手JPA 2.0单元测试 作为一个Java开发 我想:

  • 所有测试套件前一次初始化一个EntityManagerFactory实例。我使用@BeforeClass注释
  • 实例化一个EntityManager实例和每个测试用例之前启动一个新的事务,并回滚之前像AOP的开始交易达成目的/后或around通知
  • 能够让任何设置/在任何衍生测试套件之前/之后的拆卸操作

我一直在编写JUnit测试。但在这种情况下,我对列表中的第二项和第三项产生了问题。

请看看下面的测试套件的例子:

抽象测试套件

public abstract class AbstractPersistenceTest { 

    protected static EntityManagerFactory emf; 
    protected EntityManager em; 

    @BeforeClass 
    public static void setUpClass() { 
     emf = Persistence.createEntityManagerFactory("test"); 
    } 

    @Before 
    public void setUp() { 
     em = emf.createEntityManager(); 
     em.getTransaction().begin(); 
    } 

    @After 
    public void tearDown() { 
     em.getTransaction().rollback(); 
     em.close(); 
    } 

    @AfterClass 
    public static void tearDownClass() { 
     emf.close(); 
    } 

} 

派生测试套件

public class EmployeeJpqlTest extends AbstractPersistenceTest { 

    private Employee john; 
    private Employee jack; 

    @Before 
    public void setUp() { 
     john = new Employee("John Doe", 1000); 
     jack = new Employee("Jack Line", 1010); 

     em.persist(john); 
     em.persist(jack); 
    } 

    @Test 
    public void itShouldRetrieveAllEmplloyees() { 
     TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employee e", 
       Employee.class); 
     List<Employee> employees = query.getResultList(); 

     assertArrayEquals(new Employee[] { john, jack }, employees.toArray()); 
    } 

    @Test 
    public void itShoulRetrieveAllEmployeeNames() { 
     TypedQuery<String> query = em.createQuery(
       "SELECT e.name FROM Employee e", String.class); 
     List<String> names = query.getResultList(); 

     assertArrayEquals(new String[] { john.getName(), jack.getName() }, 
       names.toArray()); 
    } 

} 

由于不确定的JUnit生命周期注释的顺序NullPointerException在th中占据一席之地e派生类中的setUp()方法。对我来说很清楚。

有没有可能在没有在任何派生测试套件类的每个setUp()/ tearDown()方法中手动注入启动/回滚事务代码的情况下获得目标? 或者,也许有没有其他的JUnit平均或测试框架可以提供一种简单的方式来表达我的需求?

在此先感谢。

回答

2

您如何使用Google Guice将实体管理器和事务注入您的测试方法?

import com.google.inject.persist.Transactional; 
import javax.persistence.EntityManager; 

public class MyTest { 
     @Inject EntityManager em; 

     @Test 
     @Transactional 
     public void createNewPerson() { 
       em.persist(new Person(...)); 
     } 
} 

它可以简化这方面的大量工作。

+0

是的,这是个好主意。由于Google Guice是一款精益IoC,因此可以在不受代码影响的情况下使用。 –

1

为什么不在setUp,super.setUpClass等电话super.setUp()?你实际上在做的是重写子类的方法。

+0

其实我是这样做的,因此在测试运行期间,父行器的'setUp()'方法在一行中被调用两次 - 直接从我的代码执行一次,第二次由JUnit执行与JUnit生命周期相关的操作。 –

1

考虑使用Spring处理非静态实体管理器和事务回滚的一次性实例化。即使你没有在你的应用程序中使用Spring,你也可以在测试中使用它。详情请参阅http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/testing.html的第9.3节。

+0

是的,我完全同意你的看法。这是一个非常方便的选择。这个特别的项目非常小巧,所以我避免使用Spring,理解我拒绝的东西。谢谢。 –