0

私は自分のプロジェクト (spring + hibernate) のテストを書きたいと思っています。テストにはインメモリ データベース (hsqldb) を使用します。そして、データベースにデータを入力する必要があります。私にとっては、 @BeforeClass メソッドを使用するのが最善の方法です。このようなもの

@Transactional
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:test-applicationContext.xml")
public class UsersControllerTest {

    @Autowired
    private static SessionFactory sessionFactory;

    @BeforeClass
    public static void setUpBeforeClass() {
            User u = new User();
            u.setLogin("test_login");
            u.setPassword("test_password");
            u.setName("test_name");

            Session session = sessionFactory.getCurrentSession();
            session.save(u);
    }

しかし、この場合 sessionFactory が null になるため、これを行うことはできません。@BeforeClass の代わりに @Before メソッドを使用すると機能します。しかし、このメソッドはすべての @Test メソッドの前に実行され、必要がないため、これは良い解決策ではないと思います。だから私の質問は簡単です。データベースにテスト データを作成する必要がある場合、この状況に最適なソリューションはどれですか?

4

1 に答える 1

0

@Beforeメソッド内のコードが繰り返し実行されるのを防ぐために、単純に静的ブール値フラグを使用するのはどうでしょうか。このようなもの:

public class UsersControllerTest {

    private static boolean isDataSetLoaded = false;

    @Autowired
    private SessionFactory sessionFactory;

    @Before
    public void setUp() throws Exception {
        if (!isDataSetLoaded) {
            loadDataset();
            isDataSetLoaded = true;
        }
    }

    private void loadDataset() throws Exception {
        // save various entities here
    }
}

アップデート:

深刻な頭痛の種となった上記のソリューションの警告に注意を向けたいと思います。

この@Transactionalサポートは、Spring によって非常に直感に反する方法で実装されています。テスト メソッドに入る直前にトランザクションが開かれることを期待しますが、実際には、@Before注釈付きメソッドが実行される前であっても、トランザクションはより早い段階で既に開かれています。

loadDataset()これは、最初のテスト メソッドと同じトランザクション内でデータ操作が実行されることを意味します。これは大きな問題です@Transactional。テスト メソッドのデフォルトの動作は最後にロールバックするためです。最終的な結果として、最初のloadDataset()テスト メソッドの後にすべての初期化ステップが元に戻されるため、準備されたデータに依存している場合、後続のテスト メソッドは失敗します。

もちろん、これは、 の操作loadDataset()が既存のトランザクションに参加しようとする場合にのみ問題になります。これは、適切なトランザクション属性を適用することで防止できます (例: TransactionTemplatewithを使用Propagation.REQUIRES_NEW)。

于 2013-03-07T14:39:01.350 に答える