[rspec-users] how can this pass?

Pat Maddox pergesu at gmail.com
Tue Feb 10 03:54:56 EST 2009


On Mon, Feb 9, 2009 at 10:18 PM, Sergio Bayona <lists at ruby-forum.com> wrote:
> Mark Wilden wrote:
>> On Sun, Feb 8, 2009 at 6:54 PM, Sergio Bayona <lists at ruby-forum.com>
>> wrote:
>>
>>> > On Mon, Feb 9, 2009 at 2:35 AM, Sergio Bayona <lists at ruby-forum.com>
>>> > wrote:
>>> >>
>>> >>        assigns[:property].should equal(mock_property)
>>> >> 1 example, 0 failures
>>> >>
>>> >>
>>> >> why zero failures? more specifically, why would :non_existing_method
>>> >> return mock_property?
>>>
>>
>> Dogpile!
>>
>> ///ark
>
> Evidently I'm still not fully getting it... why would this not pass? I
> mean I know why it doesn't pass. One instance is a mock object and the
> other is an AR object. But, shouldn't it return the mock property?
> There's just something elemental about Rspec I still don't get.
>
>
>
>  describe "responding to GET new" do
>
>    it "should expose a new property as @property" do
>      @account = mock_model(Account)
>      @account.should_receive(:properties)
>      @property = mock_model(Property, :new_record? => false, :errors =>
> [])
>      @account.properties.should_receive(:build).and_return(@property)
>      get :new
>      assigns[:property].should == @property
>    end
>
>  end
>
>  def new
>    @property = @account.properties.build
>
>    respond_to do |format|
>      format.html # new.html.erb
>      format.xml  { render :xml => @property }
>    end
>  end
>
>
>
> 'PropertiesController responding to GET new should expose a new property
> as @property' FAILED
> expected: #<Property:0x1191b84 @name="Property_1002">,
>     got: #<Property id: nil, name: nil, address: nil, city: nil, state:
> nil, zip: nil, uasap: nil, tax_number: nil, rent_due: nil, units_count:
> 0, issues_count: 0, account_id: 1, created_at: nil, updated_at: nil>
> (using ==)
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>

Hi in your new method, where does @account come from?  Is it loaded
through some kind of before_filter, or as part of the authentication
framework?

Anyway, once you've built up your mock expectations you now need to
inject the mock into the code.  You do this by stubbing the code that
loads up the @account object - typically you're just doing an
Account.find call somewhere.  Note also that you need to specify that
account returns something when properties is called - you need to hook
up the association proxy.

it "should expose a new property as @property" do
     @account = mock_model(Account)
     Account.should_receive(:find).with("1").and_return @account
     @account.stub!(:properties).and_return mock('properties proxy')
     @property = mock_model(Property, :new_record? => false, :errors =>
[])
     @account.properties.should_receive(:build).and_return(@property)
     get :new
     assigns[:property].should == @property
   end
end

additionally I would only have two expectations (should_receive) and
would loosen the rest by just stubbing:

it "should expose a new property as @property" do
     # arrange
     @account = mock_model(Account, :properties => mock('properties proxy'))
     @property = mock_model(Property, :new_record? => false, :errors =>
[])
     @account.properties.stub!(:build).and_return(@property)

     # sanity check
     Account.should_receive(:find).with("1").and_return @account

     # act
     get :new

     # assert
     assigns[:property].should == @property
   end
end

I like to minimize the number of expectations(/assertions) that appear
in the example.  Doing so clearly communicates the important behavior.
 If the final expectation passes, you can infer that it's doing the
right thing with the model because that's the only way to get to your
mock @property.  Finally I threw in an Account.should_receive("1")
because you need to inject the mock account somehow.  That does the
trick, and it also serves as a sanity check for the contract between
controller and model - Account.find is the entry point to the model in
this action.

Does that make sense?

Pat


More information about the rspec-users mailing list