2013-08-09 9 views
7

MySqlを使用するRails 4.0アプリケーションでは、rspecをstrategy:transactionで設定されたdatabase_cleaner gemと一緒に使用して、テストケースごとにデータベースをクリーンアップします。ロールバックする必要があるカスタムトランザクションがある場合、機能しません。 database_cleaner宝石とちょうど標準的な方法を使用せずにカスタムトランザクションはrspecのdatabase_cleanerで動作しません

config.use_transactional_fixtures = true 

すべてがようaspected動作します。しかし、JavaScriptを使って機能テストを実行するには、fixtureの削除戦略を切り捨てるためにdatabase_cleanerが必要です。

database_cleanerをカスタムトランザクションと一緒に使用するにはどうすればよいのですか?また、標準rspecトランザクション戦略と異なる点は何ですか?

+0

私はあなたが知っていると確信しています:DatabaseCleaner.strategy =:deletion/DatabaseCleaner.strategy =:切り捨て、あなた自身を言及しているので。私はこれがdatabase_cleanerの:トランザクション戦略の中の問題であるかどうか、またはこれが予期せず動作するネストされたトランザクションの場合の一般的な問題であるかどうかには依然として関心があります。 –

答えて

11

問題は、database_cleanerがテストの最後にActiveRecord.rollbackを呼び出します。これはコードでも使用します。 InnoDB/MySQLは真のネストされたトランザクションをサポートしていないので、コード内のネストされたトランザクションは、明示的にコールされない限り、真にトランザクションとして扱われません。

は、(ActiveRecordのドキュメントから)、このブロックを考えてみましょう:

User.transaction do 
    User.create(username: 'Kotori') 
    User.transaction do 
    User.create(username: 'Nemu') 
    raise ActiveRecord::Rollback 
    end 
end 

あなたはロールバック・コールの後に起こることを期待しますか?あなたはNemuのユーザーをロールバックし、Kotoriであなたを残すことを期待していますよね?まあ、実際に起こるのは、KotoriとNemuの両方が作成されているということです。ネストされたトランザクション(ARは現在のところ親を気にします)と親トランザクション(実際のdbトランザクションを持つ)はロールバック呼び出しを表示しないため、ロールバックはトリガされません孤立したブロックそれは奇妙だ。

ソリューション

Klass.transaction(requires_new: true) 

あなたはREQUIRES_NEW設定した場合、ActiveRecordのは使いますか疑似使用し、ネストされたトランザクションを(Postgresのためには、ネストされたトランザクションを作ってあげる、MySQLの/ InnoDBのためにそれはセーブポイントを作成します)。 ActiveRecordでロールバックを呼び出すと、スコープがわかり、適切なロールバックを発行します。

他の解決方法は、トランザクションを含むテストの戦略として切り捨てまたは削除を使用することです。

+0

大きな説明。ありがとう! –

関連する問題