2012-05-28 6 views
5

JUnitでいくつかのテストスイートを実行するにはライフサイクルの問題があります。JUnitライフサイクル

  • は、すべてのテストスイートの前に一度のEntityManagerFactoryインスタンスを初期化します。便利なJPA 2.0ユニットを書き込むためには

    は、私がしたいJava開発者 として をテストします。 @BeforeClass注釈を使用してオブジェクトを実現する

  • EntityManagerインスタンスをインスタンス化し、各テストケースの前に新しいトランザクションを開始し、AOP前後の開始トランザクションをロールバックする前後のアドバイス
  • セットアップ/派生したテストスイートの前/後の操作を破る

私はJUnitテストをたくさん書いています。しかし、このような場合、リストの2番目と3番目の項目に問題があります。

次のテストスイートの例を見てみてください。

抽象テストスイート

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

super.setUp()setUpsuper.setUpClassなどと呼びますか?あなたが実際にやっていることは、サブクラスのメソッドをオーバーライドすることです。

+0

実際、私はそのようにしていました。その結果、テスト実行中に親の 'setUp()'メソッドが2回連続して呼び出されました。コードから直接1回、JUnitのライフサイクルに関して2回目です。 –

1

非静的エンティティマネージャとトランザクションロールバックの1回限りのインスタンス化を処理するためにSpringを使用することを検討してください。アプリケーションでSpringを使用していなくても、テストで使用するだけで恩恵を受けることができます。詳細は、9.3.3 http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/testing.htmlを参照してください。

+0

はい、私はあなたに完全に同意します。それは素晴らしい便利な選択肢です。その特定のプロジェクトはとても小さくてシンプルなので、私が拒否したことを理解して、Springを使うことは避けてください。ありがとう。 –