Describe AddressesController, "handling GET /addresses" do

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:

  1. 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:

  1. 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