How to stub the :current_user and any methods associated with it

I’m new to Rspec and I’m having a bit of trouble with this controller
that I’m testing. I think I’m doing it right but I guess my syntax is
wrong.
I’m currently using the “acts_as_authenticated” plug in.

What I want to test out is

EventController on entering the tickets_page

  • should show the tickets_page if the current_user has NOT entered
    this page today

Below is my event controller

class EventController < ApplicationController

before_filter :login_required

def tickets_page
if current_user.has_already_entered_today?
flash[:notice] = ‘Come back tomorrow’
redirect_to :action => ‘home’
else
flash[:notice] = ‘Welcome’
end
end
end


Below is my rspec for this controller

require File.dirname(FILE) + ‘/…/spec_helper’
describe EventController do

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

fixtures :users

describe “on entering the tickets page” do
it “should show the tickets_page if the current_user has NOT
entered this page today” do
controller.current_user.stub!
(:has_already_entered_today?).and_return(:false)
get :tickets_page

controller.current_user.should_receive(:has_already_entered_today?).with(:false).and_return(:false)
response.should render_template(:tickets_page)
end
end

end


My errors

Mock ‘User_1001’ received unexpected
message :has_already_entered_today? with (no args)

Anyone can help with any direction of what I might be doing wrong?

Responses shown below…

Sorry this isn’t extremely informative … in a bit of a rush. Hopefully
it
will point you in the appropriate direction.

On Sun, Apr 6, 2008 at 2:17 PM, newbie [email protected] wrote:

 if current_user.has_already_entered_today?

Below is my rspec for this controller

Mock ‘User_1001’ received unexpected
message :has_already_entered_today? with (no args)

So this is a good start … it means that the controller action is
actually
being mocked out … you just need to keep moving forward
mocking/stubbing
out the rest of your controller actions. it’s complaining that it
doesn’t
know what to do on your current_user.has_already_entered_today?
method.

@current_user.stub!(:has_already_entered_today?).and_return()

rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users


Bryan R.

“Programming today is a race between software engineers striving to
build
bigger and better idiot-proof programs, and the Universe trying to
produce
bigger and better idiots. So far, the Universe is winning.”

Thanks for the direction. I’m glad to hear that I’m going in the right
direction. I just have a final question and I seem to be hitting a
stub/mocking road block at the moment. In my controller I have this…

def index
@entries = current_user.entries
end

How would I rspec this out correctly? This is what I have but it looks
wrong.

before(:each) do
@current_user = mock_model(User, :id => 1)
@entry = mock_model(Entry, :user_id => 1)
controller.stub!(:current_user).and_return(@current_user)
controller.stub!(:entries).and_return(@entry)
end

describe “on the index page” do
it “should show all of the current_users entries” do

@current_user.should_receive(:entries).with(@entry).and_return(true)
end
end

On 11.4.2008, at 4.57, newbie wrote:

@current_user.should_receive(:entries).with(@entry).and_return(true)

This is wrong. The with method means parameters the expected method
call receives. In your case it gets no parameters. Besides, since you
stub the entries method anyway, you can just specify the behaviour.

What you probably want with the code above is this:

assigns[:entries].should == @entry

//jarkko

EventController on entering the tickets_page


end
controller

method.

rspec-users mailing list
bigger and better idiots. So far, the Universe is winning."


rspec-users mailing list
[email protected]://rubyforge.org/mailman/listinfo/rspec-users


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users


Jarkko L.

http://www.railsecommerce.com
http://odesign.fi

Hey Jarkko,

Thanks for the feedback. I tried your suggestion and it doesn’t seem
to work.

To quickly recap I’m just testing in my controller that this works

def index
@entries = current_user.entries
end

describe “on the main page” do
it “should show all the current entries for the user” do
get :index
assigns[:entries].should == @entries
end

On 12.4.2008, at 22.24, newbie wrote:

Hey Jarkko,

Thanks for the feedback. I tried your suggestion and it doesn’t seem
to work.

What doesn’t work?

get :index
assigns[:entries].should == @entries
end

I don’t see you logging in a user anywhere.

//jarkko


Jarkko L.

http://www.railsecommerce.com
http://odesign.fi

Not sure why you are stubbing entries on the controller … entries is
called on the current user …

I have this method. I want to use this variable to loop the users
@entries. So I’m testing to see that this variable is tested and works
correctly.

def main
@entries = current_user.entries
end

I tried your suggestion
@current_user = mock_model(User, :id => 1, :entries => [@entry])

My error
“Mock ‘User_1010’ received unexpected message :entries with (no args)”

Maybe this is overtesting or not really necessary to test. Let me
know.


I’m testing this out

def main
@entries = current_user.entries
end


Using this spec

before(:each) do
@current_user = mock_model(User, :id => 1)
@entry = mock_model(Entry, :user_id => 1)
controller.stub!(:current_user).and_return(@current_user)
controller.stub!(:login_required).and_return(:true)
controller.stub!(:entries).and_return(@entry)
end

describe “on the main page” do
it “should show all the current entries for the user” do
@current_user = mock_model(User, :id => 1, :entries => [@entry])
get :main
end
end

On Apr 15, 2008, at 7:08 PM, newbie wrote:

end

@current_user = mock_model(User, :id => 1, :entries => [@entry])
get :main
end
end

@current_user is being assigned values twice - once in before(:each)
and once in describe “on the main page”.

The mock that is raising the error is the one defined in
before(:each), which is the one that is NOT told to expect :entries,
and is the one that is returned by controller.current_user (per the
3rd line of before(:each)).

That all make sense? Not really a mock or rspec problem but really
just understanding how assignments work in Ruby.

HTH,
David

Looking at yr earlier post …

controller.stub!(:entries).and_return(@entry)

Not sure why you are stubbing entries on the controller … entries is
called on the current user …

I tend to do this …

@current_user = mock_model(User, :id => 1, :entries => [@entry])

HTH
Shane

I’m also having problems stubbing current_user.

I cannot put
controller.stub!(:current_user).and_return(@current_user)
in a before(:all) block. The stubbing doesn’t happen.

However if I put it in the it “should…” block, then it works.

Why is that?

Actually, in a before(:each) block, the stubbing works. So why doesn’t
it work with a before(:all)?

On Wed, Nov 5, 2008 at 8:05 AM, Fernando P. [email protected]
wrote:

I’m also having problems stubbing current_user.

I cannot put
controller.stub!(:current_user).and_return(@current_user)
in a before(:all) block. The stubbing doesn’t happen.

Stubs and mocks get cleared out after each example. before(:all) only
runs once, so after the first example in a group runs, the stub gets
cleared out and does not get recreated.

before(:each) runs before each example, setting the stub each time.

So use before(:each) instead of before(:all).

Make sense?

There’s a little more info about this on
http://rspec.info/documentation/before_and_after.html (near the
bottom).

Cheers,
David

Thanks for the clarification. And from now on I will quote previous
emails.

On Wed, Nov 5, 2008 at 8:06 AM, Fernando P. [email protected]
wrote:

Actually, in a before(:each) block, the stubbing works. So why doesn’t
it work with a before(:all)?

Please, please, please quote the information from the previous email
to which you are referring. I’ll respond to your first email.

On Wed, Nov 5, 2008 at 8:22 AM, Fernando P. [email protected]
wrote:

Thanks for the clarification. And from now on I will quote previous
emails.

Sorry man, but I’m laughing my ass off over this.

Readers of this email will have no idea what I clarified for you
because you didn’t quote the clarification :slight_smile: :slight_smile: :slight_smile:

We’ll keep working on this and get it right sooner or later.

Cheers,
David