統合テストから Grails/Hibernate にデータベース スキーマを強制的に再作成させる便利な方法はありますか?
3 に答える
DataSource.groovy
空のデータベースに以下を追加すると、統合テストが実行される前に作成されます。
environments {
test {
dataSource {
dbCreate = "create"
}
}
}
デフォルトでは、各統合テストは、テストの最後にロールバックされるトランザクション内で実行されるため、このデフォルトの動作を使用しない限り、プログラムでデータベースを再作成する必要はありません。
アップデート
あなたのコメントに基づいて、統合テストの前にスキーマを再作成したいようです。その場合、私が考えることができる唯一の方法は、実行することです
- スキーマを削除して再作成する
- grails schema-exportを使用して新しいスキーマをインポートする
class MyIntegrationTest {
SessionFactory sessionFactory
/**
* Helper for executing SQL statements
* @param jdbcWork A closure that is passed an <tt>Sql</tt> object that is used to execute the JDBC statements
*/
private doJdbcWork(Closure jdbcWork) {
sessionFactory.currentSession.doWork(
new Work() {
@Override
void execute(Connection connection) throws SQLException {
// do not close this Sql instance ourselves
Sql sql = new Sql(connection)
jdbcWork(sql)
}
}
)
}
private recreateSchema() {
doJdbcWork {Sql sql ->
// use the sql object to drop the database and create a new blank database
// something like the following might work for MySQL
sql.execute("drop database my-schema")
sql.execute("create database my-schema")
}
// generate the DDL and import it
// there must be a better way to execute a grails command from within an
// integration test, but unfortunately I don't know what it is
'grails test schema-export export'.execute()
}
@Test
void myTestMethod() {
recreateSchema()
// now do the test
}
}
何よりもまず、このコードは完全にテストされていないため、深い疑念と低い期待をもって扱ってください。次に、これを機能させるために、統合テストのデフォルトのトランザショナル動作を変更する必要がある場合があります ( を使用@Transactional
)。
これは正常に機能しているように見えますが、明らかに H2 と非常に緊密に結合されているため、Hibernate プラグインがこれを処理する API を公開していればよかったでしょう。
http://h2database.com/html/grammar.html#script
class SomethingTestingTransactionsSpec extends IntegrationSpec {
static transactional = false // Why I need this
SessionFactory sessionFactory // Injected by Spring
DataSource dataSource // Also injected
File schemaDump
Sql sql
void setup() {
sql = new Sql(dataSource)
schemaDump = File.createTempFile("test-database-dump", ".sql") // Java 7 API
sql.execute("script drop to ${schemaDump.absolutePath}")
}
void cleanup() {
sql.execute("runscript from ${schemaDump.absolutePath}")
sessionFactory.currentSession.clear()
schemaDump.delete()
}
// Spock tests ...
}
このコードをテスト環境用にのみ登録された Bean に抽出するのは簡単です。これにより、テスト コードが少しクリーンアップされ、スキーマを 1 回ダンプするだけで効率が向上します。
sessionFactory を介して任意の SQL を実行できるため、テストの開始時に Grails スキーマ エクスポートを呼び出し、必要に応じてスキーマを DB に再インポートすることができます。
あるいは、データベース移行プラグインを外部から呼び出すことで同じことが達成されるのだろうか。
または、grails をだましてドメイン クラスが変更されたと認識させ、https://github.com/grails/grails-core/blob/v2.1.1/grails-hibernate/src/main/groovy/org/codehausから強制的にリロードすることもできます。 /groovy/grails/plugins/orm/hibernate/HibernatePluginSupport.groovy#L340 (方法は聞かないでください)