2014年9月22日月曜日

rspecとfactory_girlのテストでトランザクション効かせる

railsのmodelのテストをrspecで作成していて、factory_girlで作ったデータでテストをした際に、
テストが完了したらテスト用データも削除されるようにしたいので、そのときにやった対応です。

テスト対象テーブルはこんな感じです。
mysql> select * from seq_sometest4s;
+----+--------+
| id | seq_id |
+----+--------+
|  1 |      1 |
+----+--------+
1 row in set (0.00 sec)

テストしたいクラスです。
$ cat app/models/concerns/seq_table.rb 
module SeqTable
 
  def seq_incrment(klazz)
    base = Object.const_get(klazz)
    base.transaction do
    tbl = base.lock.find(1)
 
    tbl.increment!(:seq_id)
    tbl.seq_id
  end
  rescue => e
    raise e
  end
end
 
$ cat app/models/seq_sometest4.rb 
class SeqSometest4 < ActiveRecord::Base
end

$controller抜粋
seq_id = seq_incrment("SeqSometest4")

spec/rails_helper.rbに設定
config.use_transactional_fixtures = true

まずテストを書いてみました。
require 'rails_helper'
 
describe "SeqTable" do
  include SeqTable
 
  seq = FactoryGirl.create(:seq_sometest4)
  context "#seq_incrment" do
    it {
      res = seq_incrment("SeqSometest4")
      expect(res).to eq (seq.seq_id + 1)
    }
  end
end

これだと、テスト終了後にデータが残ってしまいました。
mysql> select * from seq_sometest4s;
+----+--------+
| id | seq_id |
+----+--------+
|  1 |      1 |
+----+--------+
1 row in set (0.00 sec)

FactoryGirlの処理をit{}の中に持ってきてみました。
require 'rails_helper'
 
describe "SeqTable" do
  include SeqTable
 
  context "#seq_incrment" do
    it {
      seq = FactoryGirl.create(:seq_sometest4)
      res = seq_incrment("SeqSometest4")
      expect(res).to eq (seq.seq_id + 1)
    }
  end
end

mysql> select * from seq_sometest4s;
Empty set (0.00 sec)

itの中に書くことでテスト内での操作ってことになって、トランザクション内での処理ってことになるのかなと。


参考URL
https://relishapp.com/rspec/rspec-rails/docs/transactions

0 件のコメント:

コメントを投稿