[rspec] Stubbing partials in view specs


#1

Hey list,

As a good BDDer I want to test my views in isolation. And as a good
rails programmer, I separate views into partials when needed. So,
when testing my views, I want to stub out rendering of partials in my
views. I’m working on upgrading an app from rails 2.1.2 to 2.2.2,
using the latest rspec and rspec-rails.

I used to throw template.stub!(:render) in a before(:each) block and
be done with it, but that doesn’t work anymore. I can understand why,
but now I have to do something like template.stub!(:render).with
(hash_including(:partial => anything)). Except for when I’m testing a
partial, then I need to replace the anything with every partial I’m
rendering in my partial.

Is this the correct way, or is there perhaps something like
template.stub_partials :only => [], :except => [] ?

thanks,
bartz


#2

On Tue, Jan 20, 2009 at 7:44 AM, Bart Z.
removed_email_address@domain.invalid wrote:

Hey list,

As a good BDDer I want to test my views in isolation.

Sort of. A good BDDer wants to specify views in isolation. Testing
is for testers :slight_smile:

And as a good rails
programmer, I separate views into partials when needed. So, when testing my
views, I want to stub out rendering of partials in my views. I’m working on
upgrading an app from rails 2.1.2 to 2.2.2, using the latest rspec and
rspec-rails.

I used to throw template.stub!(:render) in a before(:each) block and be done
with it

That sounds kinda risky because you could be ignoring partials that
get rendered that you don’t want to be rendered.

, but that doesn’t work anymore. I can understand why, but now I have
to do something like template.stub!(:render).with(hash_including(:partial =>
anything)). Except for when I’m testing a partial, then I need to replace
the anything with every partial I’m rendering in my partial.

Is this the correct way,

Seems like the only way at the moment. Wouldn’t call it correct or
incorrect.

or is there perhaps something like
template.stub_partials :only => [], :except => [] ?

Nothing like this exists. Seems like a reasonable idea. Feel free to
submit a feature request, or better yet, a patch to
http://rspec.lighthouseapp.com

Cheers,
David


#3

On 20-jan-2009, at 15:29, David C. wrote:

On Tue, Jan 20, 2009 at 7:44 AM, Bart Z.
removed_email_address@domain.invalid wrote:

Hey list,

As a good BDDer I want to test my views in isolation.

Sort of. A good BDDer wants to specify views in isolation. Testing
is for testers :slight_smile:

You’re right! I tend to talk a lot to non-programmers, and they get
that glaze-in-the-distance look in their eyes, whenever I mention
specifiy, spec’ing, or what have you :).

and be done
with it

That sounds kinda risky because you could be ignoring partials that
get rendered that you don’t want to be rendered.

It is, most definately.

incorrect.
I would call it ugly :). Not only do I have to remember the
hash_including part, but also the anything (and not :anything).
Conceptually, I like the template.stub!(:render). I render a
template, on which I stub all the renders. Whether that’s risky or
not is a different discussion.

or is there perhaps something like
template.stub_partials :only => [], :except => [] ?

Nothing like this exists. Seems like a reasonable idea. Feel free to
submit a feature request, or better yet, a patch to
http://rspec.lighthouseapp.com

Will do!

cheers,
bartz


#4

Hello,
I have a problem similar to one mentioned in this post.
I call a partial inside another partial.
_mother.haml contains:
render :partial => “children/child”

In mother_spec.rb file I am trying to stub the render call.
Here is a working version:

template.should_receive(:render)
template.stub!(:render)

render :partial => 'mother'

============
I would prefer to specify that the partial I am stubbing is “children/
child”,
however the following code doesn’t work for me:

template.stub!(:render).with(hash_including(:partial => 'children/

child’))
template.expect_render(:partial => ‘children/child’)

render :partial => 'mother'

: Mock ‘render_proxy’ expected :render with ({:partial=>“children/
child”}) once, but received it 0 times

Is it possible to stub the render call with specific partial name?

Thank you in advance,
Evgeny


#5

On Wed, Mar 18, 2009 at 4:35 PM, Nick H. removed_email_address@domain.invalid
wrote:

template.stub!(:render)
however the following code doesn’t work for me:
Is it possible to stub the render call with specific partial name?
use #expect_render .
#expect_render is deprecated prior to 1.2 and it has been removed 1.2.
You don’t want to use that. :slight_smile:

I hope that helps. Cheers,
Nick


rspec-users mailing list
removed_email_address@domain.invalid
http://rubyforge.org/mailman/listinfo/rspec-users


Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com


#6

Hey there Evgeny. My response is inline.

I call a partial inside another partial.
_mother.haml contains:
render :partial => “children/child”

In mother_spec.rb file I am trying to stub the render call.
Here is a working version:

template.should_receive(:render)
template.stub!(:render)

render :partial => ‘mother’

If you set a method expectation on an object (IE:
template.should_receive(:render) ), you don’t need to stub the method
(IE: template.stub!(:render) isn’t needed).

: Mock ‘render_proxy’ expected :render with ({:partial=>“children/
child”}) once, but received it 0 times

Is it possible to stub the render call with specific partial name?

What I said above about method expectations and method stubs also
applies here. You should remove the call to #stub! .

However, I’d be inclined to use #should_receive rather than
#expect_render :

template.should_receive(:render).with :partial => ‘children/child’
render :partial => ‘mother’

I haven’t written many view specs though, so maybe we’re supposed to
use #expect_render .

I hope that helps. Cheers,
Nick


#7

just upgraded to 1.2.0
the following code works now:

template.stub!(:render).with(hash_including(:partial => "children/

child"))
template.should_receive(:render).with(hash_including(:partial =>
“children/child”))

The only question that is left for me is about Nick’s words:
“If you set a method expectation on an object (IE:
template.should_receive(:render) ), you don’t need to stub the method
(IE: template.stub!(:render) isn’t needed).”

Basically, there are two situation.

  1. I want to check if a function was called and I want to execute the
    function code
  2. I want to check if a function was called and I don’t want to
    execute the function code so I used stubbing.

I thought that for the first scenario the solution would be:
template.should_receive(:render) #only checks if render function was
called

and for the second scenario
template.stub!(:render) #stub render function
template.should_receive(:render) #check if render function was called

Am I right?

Thanks,
Evgeny


#8

On Wed, Mar 18, 2009 at 6:18 AM, Evgeny Bogdanov
removed_email_address@domain.invalid wrote:

template.stub!(:render)

render :partial => ‘mother’

I would prefer to specify that the partial I am stubbing is “children/
child”,
however the following code doesn’t work for me:

template.stub!(:render).with(hash_including(:partial => ‘children/
child’))
template.expect_render(:partial => ‘children/child’)

What version of rspec are you using? #expect_render has been removed
in rspec 1.2 and has been deprecated for a while before that so you
won’t want to rely on that unless you’re using an old version of
rspec.

render :partial => ‘mother’

: Mock ‘render_proxy’ expected :render with ({:partial=>“children/
child”}) once, but received it 0 times

Is it possible to stub the render call with specific partial name?

You had it right, hash including should work:
template.stub!(:render).with(hash_including(:partial =>
“children/child”))

To stub all partials being rendered:
template.stub!(:render).with(hash_including(:partial => anything))

HTH,

programmer, I separate views into partials when needed. So, when

the anything with every partial I’m rendering in my partial.
not is a different discussion.
cheers,
bartz


rspec-users mailing list
removed_email_address@domain.invalid://rubyforge.org/mailman/listinfo/rspec-users


rspec-users mailing list
removed_email_address@domain.invalid
http://rubyforge.org/mailman/listinfo/rspec-users


Zach D.
http://www.continuousthinking.com
http://www.mutuallyhuman.com


#9

Basically, there are two situation.

  1. I want to check if a function was called and I want to execute the
    function code

I don’t think that’s possible. Setting a method expectation (Eg:
template.should_receive(:render)) automatically stubs #render.

  1. I want to check if a function was called and I don’t want to
    execute the function code so I used stubbing.

That’s how #should_receive works.

I thought that for the first scenario the solution would be:
template.should_receive(:render) #only checks if render function was
called

You’re correct that the only thing that’s checked is whether or not
#render was called on the “template” object. However, creating that
expectation causes RSpec to stub #render . If you want to confirm
this, call #render , and you’ll see that it returns nil. nil is the
default return value for a stubbed method.

and for the second scenario
template.stub!(:render) #stub render function
template.should_receive(:render) #check if render function was called

Mostly! All you need is the call to #should_receive . The call to
#stub! doesn’t do anything bad…it just doesn’t do anything at all.

Cheers,
Nick


#10

On Mar 19, 2009, at 10:30 AM, David C. wrote:

No. What I think you’re describing is called a test spy: a means of
monitoring interactions without changing the behavior. RSpec’s mocks
don’t provide this. The only ruby framework I’m aware of that does
is RR. There may be others.

"Before we exercise the SUT, we install a Test Spy as a stand-in for
depended-on component (DOC) used by the SUT. The Test Spy is designed
to act as an observation point by recording the method calls made to
it by the SUT as it is exercised. During the result verification
phase, the test compares the actual values passed to the Test Spy by
the SUT with the values expected by the test. "

http://xunitpatterns.com/Test%20Spy.html

Actually, the “Not A Mock” framework also supports the test spy pattern:

http://github.com/notahat/not_a_mock/tree/master

Scott


#11

On Mar 19, 2009, at 7:59 AM, Evgeny Bogdanov
removed_email_address@domain.invalid wrote:

template.should_receive(:render) ), you don’t need to stub the method
called

and for the second scenario
template.stub!(:render) #stub render function
template.should_receive(:render) #check if render function was called

Am I right?

No. What I think you’re describing is called a test spy: a means of
monitoring interactions without changing the behavior. RSpec’s mocks
don’t provide this. The only ruby framework I’m aware of that does is
RR. There may be others.

A stub (stubs!) overrides an existing method (if one exists) and
returns either self or any value you define with and_returns.

A message expectation, or mocked method (should_receive) does the same
thing plus it verifies that the message was called.

HTH,
David