开发者

How to test the update method in Rails

I am struggling with testing the update method in Rails. I am using the standard built in testing framework (test::unit) and Rails 3.0.8. I have created a minimum application for testing this now, but I can't get it to work. Here is what I do:

I create a new blank rails application:

rails new testapp

Create a model called Collection:

rails generate model collection name:string

Run rake db:migrate:

rake db:migrate

Create a controller called Collections with an update method:

rails generat开发者_运维技巧e controller collections update

In collection_controller.rb I add this minimum update method:

def update
  @collection = Collection.find(params[:id])
  @collection.update_attributes(params[:collection])
end

The test fixtures are the defaults (collections.yml):

one:
  name: MyString

two:
  name: MyString

Then I add this to the collection_controller_test.rb under functional:

test "should update collection" do
  put :update, :id => collections(:one), :collection => {:name => 'MyString2'}
  assert_equal "MyString2", collections(:one).name
end

When I run the test:

rake test:functionals

It fails with this message:

test_should_update_collection(CollectionsControllerTest) [/Users/atle/Documents/Rails/testapp/test/functional/collections_controller_test.rb:6]:
<"MyString2"> expected but was
<"MyString">.

Here are the output from test.log:

[1m[36mSQL (0.2ms)[0m  [1m SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
[0m
[1m[35mCollection Load (0.1ms)[0m  SELECT "collections".* FROM "collections" WHERE "collections"."id" = 980190962 LIMIT 1
Processing by CollectionsController#update as HTML
Parameters: {"id"=>#<Collection id: 980190962, name: "MyString", created_at: "2011-06-12 13:14:13", updated_at: "2011-06-12 13:14:13">, "collection"=>{"name"=>"MyString2"}}
[1m[36mCollection Load (0.2ms)[0m  [1mSELECT "collections".* FROM "collections" WHERE "collections"."id" = 980190962 LIMIT 1[0m
[1m[35mAREL (0.2ms)[0m  UPDATE "collections" SET "name" = 'MyString2', "updated_at" = '2011-06-12 13:14:13.394135' WHERE "collections"."id" = 980190962
Rendered collections/update.html.erb within layouts/application (1.5ms)
Completed 200 OK in 9ms (Views: 4.5ms | ActiveRecord: 1.2ms)

In the log I can see the UPDATE statement, but I never see a new SELECT statement.

Could someone explain to me what I am doing wrong please?


You can make assertions on the instance variable that is created during the HTTP response:

test "should update collection" do
  put :update, :id => collections(:one), :collection => {:name => 'MyString2'}
  assert_equal "MyString2", assigns(:collection).name
end


You're reloading the fixture data instead of reading from the db. Try something like

assert_equal "MyString2", Collection.find(collections(:one)).name

You might need to specify the id in the fixture.

Disclaimer: I haven't tested this.


My favorite variant of this:

test "should update collection" do
  coll = collections(:one)
  put :update, :id => coll, :collection => {:name => "MyString2"}
  assert_equal "MyString2", coll.reload.name
end

The assigns(:collection) trick doesn't actually guarantee the record was saved. This may not be a problem, or it may be a surprise.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜