web-dev-qa-db-ja.com

春のテストで@Testメソッドの前に一度だけデータベースにデータを入力するにはどうすればよいですか?

Junit4でSpringサービスレイヤーをテストする次の問題は、次のとおりです。すべての@Testメソッドの前に1回だけデータベースにデータを入力するスクリプトを呼び出す方法:これをすべての@Testsの前に1回実行します。

JdbcTestUtils.executeSqlScript(jdbcTemplate(), new FileSystemResource(
"src/main/resources/sql/mysql/javahelp-insert.sql"), false);

GenericServiceTestクラス(テストクラスで拡張)で@PostConstructを使用しようとしました。 @PostConstructが毎回@Testメソッドの前に呼び出されることがわかりました。興味深いのは、GenericServiceTestの@Autowiredアノテーションが付けられたメソッドでさえ、すべての@Testメソッドの前に呼び出されることです。

すべてのテストクラスの前にデータベースを設定するのではなく、春のテストの起動時に1回だけ設定します。

上記のメソッドを、Spring Testing Frameworkとjunit4を使用するすべての@Testメソッドの前に1回だけ実行する方法

ありがとうございました!

21

Springs組み込みデータベースサポートを使用する

<jdbc:embedded-database id="dataSource">
    <jdbc:script location="classpath:myScript.sql"/>
    <jdbc:script location="classpath:otherScript.sql"/>
</jdbc:embedded-database>

またはSpringsはデータベースサポートを初期化します

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:myScript.sql"/>
    <jdbc:script location="classpath:otherScript.sql"/>
</jdbc:initialize-database>

@See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html#jdbc-embedded-database-support

11
Ralph

これは、Alfredosの回答に基づいて構築されており、組み込みデータベースのデフォルトスクリプトを呼び出さずにデータベース情報を挿入する方法です。たとえば、少なくともテストでは、DDLを自動的に構築する場合に便利です。

_@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext.xml"})
public class TestClass {

    @Autowired
    private ApplicationContext ctx;

    private JdbcTemplate template;

    @Autowired
    public void setDataSource(DataSource dataSource) {
       template = new JdbcTemplate(dataSource);
    }

    private static boolean isInitialized = false;

    @Before
    public void runOnce() {
        if (isInitialized) return;
        System.out.println("Initializing database");

        String script = "classpath:script.sql"; 
        Resource resource = ctx.getResource(script);
        JdbcTestUtils.executeSqlScript(template, resource, true);            
        isInitialized = true;
    }
}
_

このように、runOnce()メソッドは、テスト実行時に1回だけ呼び出されます。 isInitializedをインスタンスフィールド(非静的)にすると、すべてのテストの前にメソッドが呼び出されます。このようにして、必要に応じて、テストを実行する前にテーブルを削除または再配置できます。

これはまだかなり汚いソリューションであり、データベースを処理する賢明な方法はラルフの答えに従っていることに注意してください。

13
Mike Adler

春のブートの場合、テスト前に起動する複数のスクリプトについて言及できます

spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql
2
Toumi

Mike Adlersの例に基づいた例ですが、JUnit 5で、Tugdualによって言及されたResourceDatabasePopulatorを使用しています。

テストクラスは、テストメソッドごとに1回作成されます。したがって、一度だけ入力したい場合は、どうにかしてそれを処理する必要があります。ここでは、静的変数を使用して行われます。

@Autowired
private DataSource dataSource;

private static boolean isInitialized;

@BeforeEach // JUnit 5
void initDatabase() {
  if(!isInitialized) { // init only once
    ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.addScript(new ClassPathResource("/sql/myscript.sql")));
    populator.execute(dataSource);
    isInitialized = true;
  }
}
0
Avec