Forum: RSpec proxy associantion on controllers

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fee80fad857baeb14ff106d71eab5332?d=identicon&s=25 Daniel Area Criações (Guest)
on 2008-12-05 14:41
(Received via mailing list)
Hello, I'm trying learn Rspec but having problems to understand when and
how
user mocks and stubs.
I have a properties_controller with to before_filter actions
(check_administrator_role e load_user)... to access index action of
properties_controller I need have a params[:user] and this parameter
will be
used to load ther user in method load_user ...

Like bellow:

  before_filter :check_administrator_role
  before_filter :load_user

  # GET /properties
  def index
    @properties = @user.properties
  end

  private
  def load_user
    @user = User.find(params[:user_id])
    if @user.nil?
      flash[:notice] = "Registro não encontrado"
      redirect_to root_path
    end
  end

But I don't know how test index and load_user without fixtures, take a
look
on my specs:

describe PropertiesController do

  def mock_property(stubs={})
    @mock_property ||= mock_model(Property, stubs)
  end

  before do
    @current_user = mock_model(User, :id => 1)
    controller.stub!(:check_administrator_role).and_return(true)
    @user = mock_model(User, :id=>1)
    controller.stub!(:load_user).and_return(@user)
  end

  describe "responding to GET index" do

    it "should expose all properties of given user as @properties" do
      @user.should_receive(:properties).and_return([mock_property])
      get :index
      assigns[:properties].should == [mock_property]
    end

  end


But I having this error:

NoMethodError in 'PropertiesController responding to GET index should
expose
all properties of given user as @properties'
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.properties
/Users/daniellopes/Trabalhos/luvima/luvima/app/controllers/properties_controller.rb:8:in
`index'
./spec/controllers/properties_controller_spec.rb:21:

So, how is the right way to mock associated records?

Thanks.



Atenciosamente,

Daniel Lopes    Area Criações
Design, Websites e Sistemas Web

Visite:  http://www.areacriacoes.com.br/projects
          http://blog.areacriacoes.com.br/

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
*
55 (31) 3077-4560  /  55 (31) 8808-8748  /  55 (31) 8737-7501
Ffcc0777b36f700d1c241dfb2a416040?d=identicon&s=25 Newman Huang (rubbit)
on 2008-12-05 14:58
try:

#@user = User.find(params[:user_id])
User.stub(:find).with(xx).and_return(@user)
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2008-12-05 15:10
(Received via mailing list)
On Fri, Dec 5, 2008 at 7:58 AM, Newman Huang <lists@ruby-forum.com>
wrote:
>
> try:
>
> #@user = User.find(params[:user_id])
> User.stub(:find).with(xx).and_return(@user)

Please quote enough of the email to which you are responding to
provide enough context so that those of us who read email on our
phones can understand.

Cheers,
David
89e57a28dfdb85e07b33f92783dbe349?d=identicon&s=25 Daniel Lopes (Guest)
on 2008-12-05 15:13
(Received via mailing list)
Thanks Newman, I already try this but get strange error:
  before do
    @current_user = mock_model(User, :id => 1)
    controller.stub!(:check_administrator_role).and_return(true)
    User.stub(:find).with(1).and_return(@user) # <=<=<=<=<=<=
  end

The error:
undefined method `stub' for #<Class:0x23a5f3c>


Atenciosamente,

Daniel Lopes    Area Criações
Design, Websites e Sistemas Web

Visite:  http://www.areacriacoes.com.br/projects
          http://blog.areacriacoes.com.br/

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
*
55 (31) 3077-4560  /  55 (31) 8808-8748  /  55 (31) 8737-7501
F68f69615423aa3851bd445409754dbf?d=identicon&s=25 Joseph Wilk (joesniff)
on 2008-12-05 15:18
(Received via mailing list)
Daniel Lopes wrote:
> Thanks Newman, I already try this but get strange error:
>
>   before do
>     @current_user = mock_model(User, :id => 1)
>     controller.stub!(:check_administrator_role).and_return(true)
>     User.stub(:find).with(1).and_return(@user) # <=<=<=<=<=<=

Looks like a missing '!':

User.stub!(:find).with(1).and_return(@user) # <=<=<=<=<=<=

--
Joseph Wilk
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2008-12-05 15:24
(Received via mailing list)
On Fri, Dec 5, 2008 at 8:07 AM, Daniel Lopes <danielvlopes@gmail.com>
wrote:
> Thanks Newman, I already try this but get strange error:
>   before do
>     @current_user = mock_model(User, :id => 1)
>     controller.stub!(:check_administrator_role).and_return(true)
>     User.stub(:find).with(1).and_return(@user) # <=<=<=<=<=<=

It's stub!, not stub :)

Cheers,
David
89e57a28dfdb85e07b33f92783dbe349?d=identicon&s=25 Daniel Lopes (Guest)
on 2008-12-05 16:07
(Received via mailing list)
Thanks for help and sorry for insistance but I don't understand aspects
on
rspec ( I think not understand how we use mocks and stubs):
The behavior of my controller is...
Before Filter:
check_administrator_role
load_user

So, in this case I want run my before filter methods in before block on
rspec, like below:

describe PropertiesController do
  def mock_property(stubs={})
    @mock_property ||= mock_model(Property, stubs)
  end

  before do
    @current_user = mock_model(User, :id => 1)  <== define a
current_user
with id 1
    controller.stub!(:check_administrator_role).and_return(true) <== and
current_user is administrator
    @params = {:user_id=>1}  <== define params
    User.stub!(:find).with(@params[:user_id]).and_return(@user) <== and
now
try fetch the user with id 1
  end

  This line will define @user variable, right?
  User.stub!(:find).with(@params[:user_id]).and_return(@user)
  But I don't need mock the @user variable to fill it with valid values
(
like user_id, name, email and etc ) ?

  I think @user content is nil and get errors from will_paginate find
method
for this reason.

  describe "responding to GET index" do

    it "should expose all properties of given user as @properties" do
      @user.should_receive(:properties).and_return([mock_property])
      get :index
      assigns[:properties].should == [mock_property]
    end

  end

thanks.

Atenciosamente,

Daniel Lopes    Area Criações
Design, Websites e Sistemas Web

Visite:  http://www.areacriacoes.com.br/projects
          http://blog.areacriacoes.com.br/

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
*
55 (31) 3077-4560  /  55 (31) 8808-8748  /  55 (31) 8737-7501
49de4cd2f26705785cbef2b15a9df7aa?d=identicon&s=25 Nick Hoffman (nickh)
on 2008-12-05 18:56
(Received via mailing list)
On 2008-12-05, at 10:06, Daniel Lopes wrote:
> Thanks for help and sorry for insistance but I don't understand
> aspects on rspec ( I think not understand how we use mocks and stubs):

Hi Daniel. If you're a bit unsure about when to use mocks vs stubs,
have a read of this article by Martin Fowler:
http://martinfowler.com/articles/mocksArentStubs.html

The short version of that article is:
-You mock objects: @photo = mock_model Photo
-You stub methods: @photo.stub!(:height).and_return(123)

> The behavior of my controller is...
> Before Filter:
> check_administrator_role
> load_user

Are you using Authlogic?

> So, in this case I want run my before filter methods in before block
> on rspec, like below:

Nope!  =)  before-filters are called when a controller action is
called; they aren't called in your specs' "before" blocks.

>     @params = {:user_id=>1}  <== define params
>     User.stub!(:find).with(@params[:user_id]).and_return(@user) <==
> and now try fetch the user with id 1
>   end

Keep in mind that it's
     before :each do
or
     before :all do

>   This line will define @user variable, right?
>   User.stub!(:find).with(@params[:user_id]).and_return(@user)

That line above tells the User class to return @user when #find is
called on it with the argument @params[:user_id] .

You don't need to create a "params" variable. Eg:

before :each do
   @user = mock_model User
   controller.stub!(:check_administrator_role).and_return(true)
   User.stub!(:find).and_return @user
end

>   But I don't need mock the @user variable to fill it with valid
> values ( like user_id, name, email and etc ) ?

If you want those methods, you'd stub them on @user, like this:
   @user = mock_model User, :name => 'Bob'
or like this:
   @user = mock_model User
   # ..some other code here..
   @user.stub!(:name).with(no_args).and_return('Bob')

>   describe "responding to GET index" do
>     it "should expose all properties of given user as @properties" do
>       @user.should_receive(:properties).and_return([mock_property])
>       get :index
>       assigns[:properties].should == [mock_property]
>     end
>   end

That looks about right.
-Nick
89e57a28dfdb85e07b33f92783dbe349?d=identicon&s=25 Daniel Lopes (Guest)
on 2008-12-06 06:29
(Received via mailing list)
Thanks a lot Nick...
No, i'm not using Authlogic because already have base project with
restful_authentication implemented with activation, roles and etc... and
when I look authlogic the project was young, I don't know now.

About Martin Fowler post, I already readed... but the problem is because
I
know the diference between mocks and stubs ( mocks really call the
method
and it fail return a error, and stubs only return the result without
check
real method, right? ) but I don't know how use it in RSpec...

I'm starting understand now in this post ( my idea is copy this thread
and
translate to portuguese to help more people)... My doubt about mock and
stubs is when I write this:

@user = mock_model User => create mock object based on User and put in
@user.

but when I write the code below, the method User.name will not be called
in
this moment, but will be called when User class try to call name and
will
return 'Bob' no matter what the real name method does... is this?
@user.stub!(:name).and_return('Bob')


About my previous code... I mocked User in instance variable @user but I
have will_paginate installed and this bring a strange error when I try:
@user.sohuld_receive(:properties).and_return([mock_property])

The error is:

1)
NoMethodError in 'PropertiesController responding to GET index should
expose
all properties of given user as @properties'
undefined method `find' for #<Class:0x23a0f64>
/Users/daniellopes/Trabalhos/luvima/luvima/vendor/gems/mislav-will_paginate-2.3.6/lib/will_paginate/finder.rb:167:in
`method_missing'
/Users/daniellopes/Trabalhos/luvima/luvima/app/controllers/properties_controller.rb:61:in
`load_user'
./spec/controllers/properties_controller_spec.rb:20:
spec/controllers/sessions_controller_spec.rb:102:

My spec code is:

describe PropertiesController do

  def mock_property(stubs={})
    @mock_property ||= mock_model(Property, stubs)
  end

  before :each do
    @current_user = mock_model(User, :id => 1)
    controller.stub!(:check_administrator_role).and_return(true)
    User.stub!(:find).and_return(@user)
  end

  describe "responding to GET index" do

    it "should expose all properties of given user as @properties" do
      @user.should_receive(:properties).and_return([mock_property])
      get :index
      assigns[:properties].should == [mock_property]
    end

  end


And my controller code where error refer is:

  private
  def load_user
    @user = User.find(params[:user_id])
    if @user.nil?
      flash[:notice] = "Registro n&atilde;o encontrado"
      redirect_to root_path
    end
  end

Atenciosamente,

Daniel Lopes    Area Criações
Design, Websites e Sistemas Web

Visite:  http://www.areacriacoes.com.br/projects
          http://blog.areacriacoes.com.br/

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
*
55 (31) 3077-4560  /  55 (31) 8808-8748  /  55 (31) 8737-7501
89e57a28dfdb85e07b33f92783dbe349?d=identicon&s=25 Daniel Lopes (Guest)
on 2008-12-06 14:35
(Received via mailing list)
Ashley Moran gave me help in another post that I open by accident when
entries in the group, and now spec passed... But I still would like to
understand more about mocks and stubs that I asked in previous email.

Thanks again and sorry many emails.

Atenciosamente,

Daniel Lopes    Area Criações
Design, Websites e Sistemas Web

Visite:  http://www.areacriacoes.com.br/projects
          http://blog.areacriacoes.com.br/

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
*
55 (31) 3077-4560  /  55 (31) 8808-8748  /  55 (31) 8737-7501
2ce9c0106b5851b2294ba5eb9f5c04bd?d=identicon&s=25 Ashley Moran (Guest)
on 2008-12-06 14:58
(Received via mailing list)
On 5 Dec 2008, at 20:31, Daniel Lopes wrote:

> Ashley Moran gave me help in another post that I open by accident
> when entries in the group, and now spec passed... But I still would
> like to understand more about mocks and stubs that I asked in
> previous email.

Yes I just noticed I re-answered a question that was solved hours ago :)

Ashley

--
http://www.patchspace.co.uk/
http://aviewfromafar.net/
This topic is locked and can not be replied to.