QA@IT

minitestでフラグを更新するテストを行ったらrollbackされてしまってうまくいかない

4872 PV

minitestでajaxでのDB更新のテストを書いているのですが、
updateした値がrollbackされてしまってうまくいきません。
うまい書き方はないでしょうか。

環境:
Mac OSX Lion
ruby 2.0.0p247
Rails 3.2.13
MariaDB 10.0.3(MySQL5.6系)

controller/lists_controller.rb

  def stock
    return redirect_to '/404.html' unless request.xhr?
    @list = List.find(params[:id])

    if @list.is_stocked?
      @list.is_stocked = false
    else
      @list.is_stocked = true
    end

    respond_to do |format|
      if @list.save
        format.js { @list }
      else
        format.js { render :action => "alert/error" }
      end
    end
  end

functional/lists_controller_test.rb

  test "is_stockedを更新する" do
    xhr :get, :stock, :id => @stock_flag_is_true.id
    assert_equal false, @stock_flag_is_true.is_stocked
    assert_response :success
  end

log/test.log

Processing by SlowLogsController#stock as JS
  Parameters: {"id"=>"6"}
   (0.9ms)  SELECT COUNT(*) AS count_all, server AS server FROM `lists` GROUP BY server
  SlowLog Load (0.7ms)  SELECT `lists`.* FROM `lists` WHERE `lists`.`id` = 6 LIMIT 1
   (0.4ms)  SAVEPOINT active_record_1
   (0.7ms)  UPDATE `lists` SET `is_stocked` = 0 WHERE `lists`.`id` = 6
   (0.4ms)  RELEASE SAVEPOINT active_record_1
  Rendered lists/_list.html.erb (54.7ms)
  Rendered lists/stock.js.erb (58.4ms)
Completed 200 OK in 81ms (Views: 67.0ms | ActiveRecord: 3.1ms)
   (2.0ms)  ROLLBACK

回答

ROLLBACK はテストの終わりに、テスト中に変更されたデータを戻すためのものだと思います。

したがって、最後の assert_response が実行されるまでは ROLLBACK されていないのではないでしょうか。
確認するためには、テストの最後に ActiveRecord::Base.logger.debug("test end") のように書いてみると、同じロガー上に出力できますので、順番が確認できます。

テストがうまくいかないのは xhr でデータベースに書き込まれたデータが stock_flag_is_true に反映されていないからだ思われます。
@stock_flag_is_true.reload.is_stocked とすると、インスタンス上の変更を破棄し、その時点でのデータベースのデータを再度読み込みますので、直るはずです。

編集 履歴 (0)
  • ご回答ありがとうございます。
    確かに、`@stock_flag_is_true`のインスタンスで更新は行われてないですね。reloadを追加してテスト通りました。

    また、処理の順も確認しました。
    仰る通り、`assert_response`の後にROLLBACKがされていました。
    重ねてありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。