Rails 3 and Rspec: counter cache column is updated to 2 if 1 is expected

I am testing an RSpec model called "Solutions" which has many Likes. The solution stores as much as he likes (counter_cache). It has the attribute "likes_count" (and the corresponding db field).

When I create a Like record related to the solution, I expect the decision attribute β€œlikes_count” to be updated from zero to 1. When I do this in the console, it works.

But when I run the specification, doing the SAME that I do in the console, it updates the TWICE field "likes_count", setting it to 2.

See (in the console) WORK :

irb(main):001:0> solution = Factory(:solution) irb(main):004:0> solution.likes_count => nil irb(main):006:0> like = Factory(:like, :likeable => solution) => #<Like id: 1, user_id: 2, likeable_id: 1, likeable_type: "Solution", created_at: "2011-11-23 19:31:23", updated_at: "2011-11-23 19:31:23"> irb(main):007:0> solution.reload.likes_count => 1 

Take a look at the result of the specification DOES NOT WORK :

  1) Solution counter cache should be increased when a like is created Failure/Error: subject.reload.likes_count.should be 1 expected #<Fixnum:3> => 1 got #<Fixnum:5> => 2 Compared using equal?, which compares object identity, but expected and actual are not the same object. Use 'actual.should == expected' if you don't care about object identity in this example. # ./spec/models/solution_spec.rb:45:in `block (3 levels) in <top (required)>' 

Here is the specification:

 describe "counter cache" do let(:solution) { Factory(:solution) } it "should be increased when a like is created" do Factory(:like, :likeable => solution) solution.reload.likes_count.should be 1 end end 

I took a look at test.log, and I realized that the db query, which updates the counter cache column, is called twice in the test.

  SQL (0.5ms) INSERT INTO "likes" ("created_at", "likeable_id", "likeable_type", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?) [["created_at", Wed, 23 Nov 2011 19:38:31 UTC +00:00], ["likeable_id", 121], ["likeable_type", "Solution"], ["updated_at", Wed, 23 Nov 2011 19:38:31 UTC +00:00], ["user_id", 204]] SQL (0.3ms) UPDATE "solutions" SET "likes_count" = COALESCE("likes_count", 0) + 1 WHERE "solutions"."id" IN (SELECT "solutions"."id" FROM "solutions" WHERE "solutions"."id" = 121 ORDER BY id DESC) SQL (0.1ms) UPDATE "solutions" SET "likes_count" = COALESCE("likes_count", 0) + 1 WHERE "solutions"."id" IN (SELECT "solutions"."id" FROM "solutions" WHERE "solutions"."id" = 121 ORDER BY id DESC) Solution Load (0.3ms) SELECT "solutions".* FROM "solutions" WHERE "solutions"."id" = ? LIMIT 1 [["id", 121]] 
+4
source share
2 answers

I had the same problem. It turned out that my spec_helper.rb loaded the models a second time and therefore created a second callback to update the counters. Make sure your solution model is not reloaded by another process.

The correct answer: you need to use == instead of be for comparison, but this will not fix the few updates that you see in your log file.

+6
source

You have an answer in your logs:

  • When you use be , it compares object_id , which is always the same for a pair of objects such as true and 1 . id of 1 looks like 2 . Try it in the console: 1.object_id #=> 2

  • So replace the test: solution.reload.likes_count.should eql 1 or even solution.reload.likes_count.should == 1

+2
source

Source: https://habr.com/ru/post/1382762/


All Articles