Today I’ve been writing some tests for a new rails 3 app, but after
reading the doc from http://rdoc.info/projects/rspec/rspec-expectations,
I still can’t understand why the test doesn’t work. My setup is:
describe “routes” do
it “should route to GET people#new” do
{:get => “/people/new”}.should route_to(:controller =>
“people”, :action => “new”)
end
end
describe “Methods” do
before :each do
@member = Factory(:member)
sign_in @member
@person = @member.build_person
end
it "should render form for a new person on GET people#new" do
@member.should_receive(:build_person).and_return(@person)
get :new
assigns[:person].should eql(@person)
response.should be_success
response.should render_template("new")
end
end
end
And the controller:
class PeopleController < ApplicationController
before_filter :authenticate_member!
Here’s how ActiveRecord defines == (to which it delegates from eql?)
It returns false if the record has no id
(!comparison_object.new_record?), even if all of the other attributes
match. In order to get this to pass you have to actually save the object
so it has an id, not just build it.
I discussed this with Rails core members a year or two ago and while
they agreed this would make testing easier, there were two motivating
arguments not to change it: a) conceptually, id-less records are not
necessarily the same entity (this one is a bit fuzzy to me) and b) it’s
a risky change given the amount of rails code in existence.
The other thing you can do is skip the stubbing and just say:
assigns(:person).should be_a_new(Person)
You could also write a custom matcher - something like
match_new_record(other) that compares all of the attributes. Maybe it’s
have_same_attributes_as:
I’d consider adding that to rspec-rails. Might be good to have a matcher
with docs that explain all this to help avoid this sort of confusion in
the future.
rspec 2.0.0.beta.17
describe “routes” do
sign_in @member
response.should render_template(“new”)
def new
PeopleController Methods should render form for a new person on GET
gender: nil, university: nil, year: nil, email: nil, phone: nil,
I’d consider adding that to rspec-rails. Might be good to have a matcher with docs that explain all this to help avoid this sort of confusion in the future.
Another option would be to add something like this:
RSpec.configure do |c|
c.treat_new_active_record_objects_as_equal
end
… and have that override ==(other) on ActiveRecord::Base. It’s
invasive, but you have to take an action to do the override.
Thanks David, this was driving me crazy. In my opinion, I think will
be a great idea to add a new matcher to rspec-rails to do this kind of
comparison better than overriding == , and have total control of what
you want to test in each case. Anyways, thanks for helping me on this.
On Jul 17, 2010, at 2:25 PM, Daniel Salmeron A. wrote:
ruby 1.9.2-rc2
describe “routes” do
sign_in @member
response.should render_template(“new”)
def new
people#new
house: nil, user_account_id: 126, user_account_type: “Member”,
I discussed this with Rails core members a year or two ago and while they agreed this would make testing easier, there were two motivating arguments not to change it: a) conceptually, id-less records are not necessarily the same entity (this one is a bit fuzzy to me) and b) it’s a risky change given the amount of rails code in existence.
Another option would be to add something like this:
RSpec.configure do |c|
c.treat_new_active_record_objects_as_equal
end
… and have that override ==(other) on ActiveRecord::Base. It’s invasive, but you have to take an action to do the override.
WDYT?
Thanks David, this was driving me crazy. In my opinion, I think will
be a great idea to add a new matcher to rspec-rails to do this kind of
comparison better than overriding == , and have total control of what
you want to test in each case. Anyways, thanks for helping me on this.
I added an issue for this:
Please share ideas there about what this matcher might look like.
Cheers,
David
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.