Pat M. wrote:
On Mon, Feb 9, 2009 at 10:18 PM, Sergio B. [email protected]
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
[email protected]
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.