Rspecing this simple controller it is driving me mad

Hi all,
here i am again with this stupid problem in rspecing
this controller action:


CommentsController
def create
@comment = Comment.new(params[:comment])
@user = User.find(params[:user_id])

[16] @comment.author = @user

@comment.save
end


CommentsController Spec
describe CommentsController, “handling POST /comments”
do

before(:each) do
@user = mock_model(User, :to_param => “2”)
@comment = mock_model(Comment, :to_param => “1”,
:author => @user)

User.should_receive(:find).at_least(1).times.and_return(@user)

Comment.stub!(:new).and_return(@comment)

end

def post_with_successful_save
@comment.should_receive(:save).and_return(true)

[34]post :create, :user_id => @user_id, :comment => {}

end

it “should create a new comment” do
Comment.should_receive(:new).with({
}).and_return(@comment)
[47]post_with_successful_save
@comment.author.should be(@user)
end

end

The frustrating error Rspec gave to me is this:

Spec::Mocks::MockExpectationError in
‘CommentsController handling POST /comments should
create a new comment’
Mock ‘Comment_1002’ received unexpected message
:author= with (#<User:0x…fdb9c1a8e
@name=“User_1000”>)
comments_controller.rb:16:in create' comments_controller_spec.rb:34:in post_with_successful_save’
comments_controller_spec.rb:47:

I have tried to google for something like this but i
resolved nothing. Could someone help me understanding
my fault?
Thanks in advance,
Roberto.

  Inviato da Yahoo! Mail.

La casella di posta intelligente.

On 6.4.2008, at 14.20, roberto belardo wrote:

[16] @comment.author = @user
@user = mock_model(User, :to_param => “2”)
def post_with_successful_save
@comment.author.should be(@user)
:author= with (#<User:0x…fdb9c1a8e
@name=“User_1000”>)
comments_controller.rb:16:in create' comments_controller_spec.rb:34:in post_with_successful_save’
comments_controller_spec.rb:47:

I have tried to google for something like this but i
resolved nothing. Could someone help me understanding
my fault?

Short answer: you haven’t stubbed the author= method for the comment
mock, only author.

A bit longer answer: Are you sure you can trust the user to only
submit valid user ids? With your current code, anyone can change the
user_id parameter in the call and fake any user id she wants. This
might be intentional (if there are only admin users in your app), just
pointing it out. You can also simplify your action by just saying
@user.comments.create(params[:comment]) once you have the user fetched.

Cheers,
//jarkko

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


Jarkko L.

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

Thank you very much for you quick answer! Naturally
now it works.
Thanks for the long version note too. I already know
that, and my code is just a test to play with rspec,
but i really appreciate your note.

Thank you for your help, see you the next problem,
Roberto. :slight_smile:

— Jarkko L. [email protected] ha scritto:

def create
describe CommentsController, "handling POST

User.should_receive(:find).at_least(1).times.and_return(@user)

`post_with_successful_save’
for the comment
pointing it out. You can also simplify your action

Jarkko L.
http://jlaine.net
http://dotherightthing.com
http://www.railsecommerce.com
http://odesign.fi


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

  Inviato da Yahoo! Mail.

La casella di posta intelligente.

Everything seemed so fine, but when i tried to
investigate a little i discovered this tremendous
behaviour of the spec:

------------------------------- CommentsController
def create
@comment = Comment.new(params[:comment])
@user = User.find(params[:user_id])
@comment.author = ‘foooooobar’
@comment.save
end

------------------------------- CommentsController
Spec
describe CommentsController, “handling POST/comments”
do
before(:each) do
@user = mock_model(User, :to_param => “2”)
@comment = mock_model(Comment, :to_param => “1”,
:author => @user)

User.should_receive(:find).at_least(1).times.and_return(@user)
Comment.stub!(:new).and_return(@comment)
@comment.stub!(:author=)
end

def post_with_successful_save
@comment.should_receive(:save).and_return(true)
@comment.should_receive(:author=)
post :create, :user_id => @user_id, :comment => {}
end

it “should create a new comment” do

Comment.should_receive(:new).with({}).and_return(@comment)
post_with_successful_save
@comment.author.should be(@user)
end
end

------------------------------- Autotest:
… 0 failures

How can the spec pass if i test that @comment.author
should be @user but in the controller i set a
fooooobar string in the @comment.author?
Better question: wich is the right way to test that
create action to be sure, it will set the author of
the comment?

— Jarkko L. [email protected] ha scritto:

might be intentional (if there are only admin users

Thanks in advance,

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

  Inviato da Yahoo! Mail.

La casella di posta intelligente.

Uhm ok, i understood your answer but autotest did not.
Better, this do not solves the problem.
If i simply remove the “stub” and the “should_receive”
for the author field, autotest will complain like
this:

Spec::Mocks::MockExpectationError in
‘CommentsController handling POST /comments should
create a new comment’
Mock ‘Comment_1008’ received unexpected message
:author= with (#<User:0x…fdb98f624
@name=“User_1006”>)

and this was the reason why i put the “should_receive”
and the “stub” on “author=” method, as someone told
previously on this ml.
:frowning:

Is there someone who knows how to spec this? Help
needed.

— Jarkko L. [email protected] ha scritto:

@user = User.find(params[:user_id])
@user = mock_model(User, :to_param => “2”)
@comment = mock_model(Comment, :to_param =>
“1”,
:author => @user)

User.should_receive(:find).at_least(1).times.and_return(@user)

it “should create a new comment” do

Comment.should_receive(:new).with({}).and_return(@comment)

should be @user but in the controller i set a

@comment.should_receive(:author=)”. The

mock, only author.
users

[email protected]



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

  Inviato da Yahoo! Mail.

La casella di posta intelligente.

On 12.4.2008, at 14.06, roberto belardo wrote:

:author= with (#<User:0x…fdb98f624
@name=“User_1006”>)

and this was the reason why i put the “should_receive”
and the “stub” on “author=” method, as someone told
previously on this ml.
:frowning:

Is there someone who knows how to spec this? Help
needed.

Two ways:

  1. either use Comment.new instead of mock_model(Comment) in your
    before block. This way your comment object has the ability to assign
    its author.
  2. Use the mock model and your should_receive test. However, after
    that you cannot test that @comment.author.should be(@user) because you
    have stubbed author= and it doesn’t really do anything. So you just
    have to rely on that it works (like you should since it’s Rails code
    which you shouldn’t really be testing).

//jarkko


Jarkko L.

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

On 8.4.2008, at 23.06, roberto belardo wrote:

end
User.should_receive(:find).at_least(1).times.and_return(@user)
it “should create a new comment” do
How can the spec pass if i test that @comment.author
should be @user but in the controller i set a
fooooobar string in the @comment.author?

Because @comment.should_receive(:author=) stubs the method so it has
no effect after that. I would advice against using it in a general
purpose helper such as post_with_successful_save and instead use it in
an actual spec if needed.

Better question: wich is the right way to test that
create action to be sure, it will set the author of
the comment?

Since you’re testing that “@comment.author.should be(@user)”, I see no
reason to explicitly have “@comment.should_receive(:author=)”. The
former correctly tests the behaviour, whereas the latter checks the
actual implementation, which in this case is superfluous. I hardly
ever use should_receive with a setter method such as author=, but it
might just be me.

Cheers,
//jarkko

@user.comments.create(params[:comment]) once you

Inviato da Yahoo! Mail.

http://dotherightthing.com

 Inviato da Yahoo! Mail.

La casella di posta intelligente.
Yahoo Search - Ricerca nel Web | Motore di Ricerca


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


Jarkko L.

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