[rspec-users] how can this pass?

Sergio Bayona lists at ruby-forum.com
Tue Feb 10 22:55:28 EST 2009


Pat Maddox wrote:
> On Mon, Feb 9, 2009 at 10:18 PM, Sergio Bayona <lists at ruby-forum.com> 
> wrote:
>>>> >>
>> other is an AR object. But, shouldn't it return the mock property?
>> [])
>>    respond_to do |format|
>>     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

Thanks Pat. You're right. Account comes from a before_filter that 
triggers this:

def current_account
   @account ||= Account.find_by_subdomain(account_subdomain)
end

I have stubbed the code on the spec_helper.rb to do that as:

def current_account(account)
   @controller.stub!(:current_account).and_return(@account = account ? 
accounts(account) : nil) #should return account fixture
end

on the property spec now I have:


describe PropertiesController do
  fixtures :accounts, :properties, :users

  before(:each) do
    current_account(:default)
    login_as(:default)
  end

  describe "responding to GET new" do

    it "should expose a new property as @property" do
      property = mock_model(Property, :new_record? => false, :errors => 
[])
      @account.properties.should_receive(:build).and_return(property)
      get :new
      assigns[:property].should == property
    end

  end
end

but now the controller complains that @account is nil:

The error occurred while evaluating nil.properties
/www/rentcloud2/app/controllers/properties_controller.rb:23:in `new'

I thought by stubbing the current_account code and returning @account, 
that'd be available to the application.
-- 
Posted via http://www.ruby-forum.com/.


More information about the rspec-users mailing list