3

以下に、単純な Rails アプリケーションのコードをいくつか示します。以下にリストされているテストは最後の行で失敗します。これは、このテストの PostController の update アクション内で投稿のupdated_atフィールドが変更されていないためです。なんで?

標準のタイムスタンプが Post モデルに含まれているため、この動作は少し奇妙に思えます。ローカル サーバーでのライブ テストでは、更新アクションから戻った後にこのフィールドが実際に更新され、最初のアサーションが満たされているため、更新アクションが正常に行われたことが示されます。

上記の意味でフィクスチャを更新可能にするにはどうすればよいですか?

# app/controllers/post_controller.rb
def update
  @post = Post.find(params[:id])
  if @post.update_attributes(params[:post])
    redirect_to @post     # Update went ok!
  else
    render :action => "edit"
  end
end

# test/functional/post_controller_test.rb
test "should update post" do
  before = Time.now
  put :update, :id => posts(:one).id, :post => { :content => "anothercontent" }
  after = Time.now

  assert_redirected_to post_path(posts(:one).id)     # ok
  assert posts(:one).updated_at.between?(before, after), "Not updated!?" # failed
end

# test/fixtures/posts.yml
one:
  content: First post
4

2 に答える 2

4
posts(:one)

これは、"posts.yml で ":one" という名前のフィクスチャを取得することを意味します。これは、テスト中に変更されることはありません。正常なテストでは場所がない、非常に奇妙で破壊的なコードを除きます。

やりたいことは、コントローラーが割り当てているオブジェクトを確認することです。

post = assigns(:post)
assert post.updated_at.between?(before, after)
于 2009-09-09T23:38:47.283 に答える
1

余談ですが、shoulda ( http://www.thoughtbot.com/projects/shoulda/ ) を使用している場合は、次のようになります。

context "on PUT to :update" do
    setup do 
        @start_time = Time.now
        @post = posts(:one)
        put :update, :id => @post.id, :post => { :content => "anothercontent" } 
    end
    should_assign_to :post
    should "update the time" do
        @post.updated_at.between?(@start_time, Time.now)
    end
end

ショタすごい。

于 2009-09-10T00:52:00.747 に答える