Hello,
I’m working with scaffold generated controller test code for handling
GET
requests. Address is the model being tested. Address belongs_to Company,
Company has_many addresses.
In my addresses_controller I have:
before_filter :get_company
def index
@addresses = @company.addresses.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @addresses }
end
end
private
def get_company
@company = Company.find_by_id(params[:company_id])
end
My controller spec code for handling GET /addresses:
before do
@company = mock_model(Company)
@addresses = mock(“addresses”)
@company.stub!(:addresses).and_return(@addresses)
Company.stub!(:find).and_return(@company)
end
def do_get
get :index, :company_id => 1
end
it “should be successful” do
do_get
response.should be_success
end
…
All of my tests (4) fail:
- NoMethodError in ‘AddressesController handling GET /addresses should
be
successful’
You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.addresses
Please, can someone explain why i’m getting nil.addresses?
Cheers!
Omar
On 21.11.2007, at 9.42, Sahyoun wrote:
@addresses = @company.addresses.find(:all)
def do_get
All of my tests (4) fail:
- NoMethodError in ‘AddressesController handling GET /addresses
should be successful’
You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.addresses
Please, can someone explain why i’m getting nil.addresses?
Since you haven’t stubbed Company.find_by_id, it goes to the
database, doesn’t find a matching row, and returns nil.
//jarkko
–
Jarkko L.
http://www.railsecommerce.com
http://odesign.fi
On Nov 21, 2007 1:15 AM, Sahyoun [email protected] wrote:
assigns[:addresses].should == [@addresses]
end
I thought @company.stub!(:addresses).and_return(@addresses) would be
sufficient for the above to pass. My understanding of mocking and stubbing
is sketchy at the moment. Any explanation on how to get this to pass would
be appreciated.
@company.stub!(:addresses).and_return([@addresses])
If you’re expecting an array, then you need the stub to return an array.
Pat
Thanks. That helped. I now have:
before do
@address = mock_model(Address)
@company = mock_model(Company)
Company.stub!(:find_by_id).and_return(@company)
@company.stub!(:addresses).and_return(@addresses)
end
with only one error remaining:
‘AddressesController handling GET /addresses should assign the found
addresses for the view’ FAILED
expected: [nil],
got: nil (using ==)
Spec:
it “should assign the found addresses for the view” do
do_get
assigns[:addresses].should == [@addresses]
end
I thought @company.stub!(:addresses).and_return(@addresses) would be
sufficient for the above to pass. My understanding of mocking and
stubbing
is sketchy at the moment. Any explanation on how to get this to pass
would
be appreciated.
Many thanks,
Omar
On Nov 21, 2007 1:35 AM, Pat M. [email protected] wrote:
do_get
If you’re expecting an array, then you need the stub to return an array.
Pat
Guh, sorry, should have looked a bit more closely:
@company.stub!(:addresses).and_return([@address])
Pat
Pat, thanks. That helped. I’m now trying to get my head around the
error:
Spec::Mocks::MockExpectationError in ‘AddressesController handling GET
/addresses/1 should be successful’
Mock ‘Address_1006’ received unexpected message :find with (“1”)
My show method in the addresses controller:
def show
@address = @company.addresses.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @address }
end
end
In the controller spec:
describe AddressesController, “handling GET /addresses/1” do
before do
@address = mock_model(Address)
@company = mock_model(Company)
Company.stub!(:find_by_id).and_return(@company)
@company.stub!(:addresses).and_return(@address)
end
def do_get
get :show, :id => “1”, :company_id => “1”
end
it “should be successful” do
do_get
response.should be_success
end
…
I know that @company.stub!(:addresses).and_return(@address) is
incorrect.
I’m trying to work out how I can stub out:
@address = @company.addresses.find(params[:id])
Thanks for any pointers.
Omar
Where does @company come from initially in the show controller? Is
there a before_filter?
describe AddressesController, “handling GET /addresses/1” do
before do
@address = mock_model(Address)
@company = mock_model(Company)
Company.stub!(:find_by_id).and_return(@company)
@company.stub!(:addresses)
@company.addresses.stub!(:find).with("1").and_return(@address)
end
end
Give that a shot, you might want to make some of those expectations
instead of stubs, depending on your style.
Nathan S.
[email protected]
rspec edge revision 2944
rspec_on_rails edge revision 2944
rails edge revision 8186
On Nov 22, 2007 3:24 AM, Sahyoun [email protected] wrote:
respond_to do |format|
before do
end
I’m trying to work out how I can stub out:
@address = @company.addresses.find(params[:id])
Thanks for any pointers.
Omar
The problem is that you didn’t stub #find on the addresses proxy.
Here’s how I’d write it:
describe AddressesController, “handling GET /addresses/1” do
before do
@address_proxy = mock(“address proxy”, :find => :address)
@company = mock_model(Company)
Company.stub!(:find_by_id).and_return(@company)
@company.stub!(:addresses).and_return(@address_proxy)
end
def do_get
get :show, :id => “2”, :company_id => “1”
end
it “should be successful” do
do_get
response.should be_success
end
it “should find the company” do
Company.should_receive(:find_by_id).with(“1”).and_return @company
do_get
end
it “should find the address” do
@address_proxy.should_receive(:find).with(“2”).and_return :address
do_get
end
it “should assign the address to the view” do
do_get
assigns[:address].should == :address
end
it “should render show.rhtml” do
do_get
response.should render_template(:show)
end
end
hth
Pat