5

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

便利な JPA 2.0 単体テストを作成するには、Java 開発者として次のことを行います。

  • すべてのテスト スイートの前に、EntityManagerFactory インスタンスを 1 回初期化します。@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 ライフサイクル アノテーションの順序が指定されていないため、派生クラスの setUp() メソッドで NullPointerException が発生します。私には明らかです。

派生したテスト スイート クラスの各 setUp()/tearDown() メソッドに手動で開始/ロールバック トランザクション コードを挿入せずに目標を達成することは可能ですか? または、おそらく、私のニーズを表現する簡単な方法を提供できる代替の JUnit 平均またはテスト フレームワークはありますか?

前もって感謝します。

4

3 に答える 3

2

Google Guiceを使用して Entity Manager と Transactions をテスト メソッドに挿入するというアイデアはいかがですか?

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(...)); 
        } 
}

この分野での多くの労力を簡素化できます。

于 2012-05-28T22:14:51.873 に答える
1

super.setUp()などに電話しsetUpてみませんsuper.setUpClassか?実際に行っているのは、サブクラスのメソッドをオーバーライドすることです。

于 2012-05-28T22:28:29.100 に答える
1

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

于 2012-05-29T06:35:59.027 に答える