On Jul 17, 2010, at 2:25 PM, Daniel Salmeron Amselem wrote:
> On Jul 17, 9:41 am, David Chelimsky <dchelim...@gmail.com> wrote:
>> On Jul 17, 2010, at 8:09 AM, David Chelimsky wrote:
>>> On Jul 17, 2010, at 3:29 AM, Daniel Salmeron Amselem wrote:
>> 
>>>> Today I've been writing some tests for a new rails 3 app, but after
>>>> reading the doc fromhttp://rdoc.info/projects/rspec/rspec-expectations,
>>>> I still can't understand why the test doesn't work. My setup is:
>> 
>>>> rvm 0.1.41
>>>> ruby 1.9.2dev (2010-07-11 revision 28618) [x86_64-darwin10.4.0] ->
>>>> ruby 1.9.2-rc2
>>>> rspec 2.0.0.beta.17
>>>> rspec-rails 2.0.0.beta.17
>>>> devise 1.1.rc2
>> 
>>>> This is the test for the controller:
>> 
>>>> require 'spec_helper'
>> 
>>>> describe PeopleController do
>> 
>>>> 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!
>> 
>>>> def new
>>>>   @person = current_member.build_person
>>>> end
>> 
>>>> end
>> 
>>>> When running the test I get:
>> 
>>>> .F.................
>> 
>>>> 1) PeopleController Methods should render form for a new person on GET
>>>> people#new
>>>>   Failure/Error: assigns[:person].should eql(@person)
>> 
>>>>   expected #<Person id: nil, first_name: nil, last_name: nil,
>>>> gender: nil, university: nil, year: nil, email: nil, phone: nil,
>>>> house: nil, user_account_id: 126, user_account_type: "Member",
>>>> home_town: nil, bio: nil, current_location: nil, high_school: nil,
>>>> undergrad: nil, profession: nil, concentration: nil, created_at: nil,
>>>> updated_at: nil>
>>>>        got #<Person id: nil, first_name: nil, last_name: nil,
>>>> gender: nil, university: nil, year: nil, email: nil, phone: nil,
>>>> house: nil, user_account_id: 126, user_account_type: "Member",
>>>> home_town: nil, bio: nil, current_location: nil, high_school: nil,
>>>> undergrad: nil, profession: nil, concentration: nil, created_at: nil,
>>>> updated_at: nil>
>> 
>>> Here's how ActiveRecord defines == (to which it delegates from eql?)
>> 
>>> http://github.com/rails/rails/blob/c6e20586372743ce200449bf0ac21aed04...
>> 
>>> 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:
>> 
>>>  assigns(:person).should have_same_attributes_as(@person)
>> 
>>> 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.
>> 
>> 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: http://github.com/rspec/rspec-rails/issues/#issue/131

Please share ideas there about what this matcher might look like.

Cheers,
David

>>> WDYT?,
>>> David
>> 
>>>>   (compared using eql?)
>>>>   # ./spec/controllers/people_controller_spec.rb:24:in `block (3
>>>> levels) in <top (required)>'
>> 
>>>> Finished in 2.29 seconds
>>>> 19 examples, 1 failure
>> 
>>>> The error with the full backtrace here:http://gist.github.com/479362
>> 
>>>> Which doesn't seem to make sense. Any ideas?
>> 
>>>> Thanks.


_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to