Class method not being stubbed


#1

Hi guys. I’m setting an expectation on a class method. For some
reason, the method isn’t being stubbed, and the expectation isn’t
seeing the call.

In KeywordListsController#create, I call the private method
#create_keywords_and_associate, which calls AdSenseHeavenParser#parse
.

Thus, some of my specs set an expectation on AdSenseHeavenParser#parse
. However, that expectation isn’t stubbing out #parse .

In the “output” section of my paste:
http://pastie.org/488160
you can see that the second line is “*** create_keywords_and_associate
***”. However, that string shouldn’t be printed if
AdSenseHeavenParser#parse is stubbed out.

I’ve been beating my head against this for a couple of hours. Any
thoughts?

Thanks,
Nick


#2

I’ve been beating my head against this for a couple of hours. Any
thoughts?
The easiest for you is to use the debugger and go through each line in
the controller.

Maybe @keyword_list.save is returning false? Stub it out and see by
yourself.


#3

On Sun, May 24, 2009 at 12:49 PM, Fernando P. removed_email_address@domain.invalid
wrote:

I’ve been beating my head against this for a couple of hours. Any
thoughts?
The easiest for you is to use the debugger and go through each line in
the controller.

Maybe @keyword_list.save is returning false? Stub it out and see by
yourself.

Hi Fernando. In this case, I don’t think it’s a matter of using the
debugger.

I’ve already stubbed out #save on @keyword_list, and confirmed that
AdSenseHeavenParser#parse is being called. I know the latter is
occuring because this is being displayed when the spec is run:
*** create_keywords_and_associate ***
If AdSenseHeavenParser#parse was actually stubbed out, or wasn’t
called at all, then that line wouldn’t be displayed.

-Nick


#4

On Sun, May 24, 2009 at 12:25 PM, Nick H. removed_email_address@domain.invalid
wrote:

Hi guys. I’m setting an expectation on a class method. For some
reason, the method isn’t being stubbed, and the expectation isn’t
seeing the call.

In KeywordListsController#create, I call the private method
#create_keywords_and_associate, which calls AdSenseHeavenParser#parse
.

Thus, some of my specs set an expectation on AdSenseHeavenParser#parse
. However, that expectation isn’t stubbing out #parse .

That’s because it isn’t a class method, it’s an instance method, so
instead of:

AdSenseHeavenParser.should_receive(:parse).with(keyword_list_contents).and_return({:keywords
=> [], :errors => []})

You should have
controller.should_receive(:parse).with(keyword_list_contents).and_return({:keywords
=> [], :errors => []})


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale


#5

On Sun, May 24, 2009 at 1:10 PM, Rick DeNatale removed_email_address@domain.invalid
wrote:

. However, that expectation isn’t stubbing out #parse .

Rick DeNatale

Hi Rick. I’m not sure what gave you the impression that #parse is an
instance method, but it definitely isn’t.

#parse is a class method inside the AdSenseHeavenParser class.
KeywordListsController doesn’t have a #parse method:
http://pastie.org/488252

-Nick


#6

On Sun, May 24, 2009 at 2:13 PM, Fernando P. removed_email_address@domain.invalid
wrote:

Hi Fernando. In this case, I don’t think it’s a matter of using the
debugger.

I suspect a problem in: require ‘lib/adsense_heaven_parser’, the code
maybe never gets out of this require statement. The debugger would allow
you to immediately clear things out.

Hi Fernando. I’m not sure what you mean by “the code never gets out of
this require statement”.

However, that doesn’t really matter. The call to #require shouldn’t
happen, because the method is supposed to be stubbed out.

-Nick


#7

Hi Fernando. In this case, I don’t think it’s a matter of using the
debugger.

I suspect a problem in: require ‘lib/adsense_heaven_parser’, the code
maybe never gets out of this require statement. The debugger would allow
you to immediately clear things out.


#8

Hi Fernando. I’m not sure what you mean by “the code never gets out of
this require statement”.
I should have said ‘the interpreter never …’

However, that doesn’t really matter. The call to #require shouldn’t
happen, because the method is supposed to be stubbed out.
You are making a lot of suppositions that are not obvious to us. Nowhere
in your pastie is your require call stubbed.


#9

On Sun, May 24, 2009 at 2:24 PM, Nick H. removed_email_address@domain.invalid
wrote:

However, that doesn’t really matter. The call to #require shouldn’t
happen, because the method is supposed to be stubbed out.

No that’s what confused me.

class KeywordListsController < ApplicationController

private

def create_keywords_and_associate(keyword_list_contents, keyword_list)
puts ‘*** create_keywords_and_associate ***’
require ‘lib/adsense_heaven_parser’
parsed_list = AdSenseHeavenParser.parse keyword_list_contents

The controller method has the require and then calls parse.

One thing which strikes me is that if Rails naming conventions were
being followed:

  1. the file name be lib/ad_sense_heaven_parser not
    lib/adsense_heaven_parser
  2. the require wouldn’t be needed since it would be autoloaded.

Perhaps the problem lies there somewhere.


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale


#10

Hi Fernando. I’m not sure what you mean by “the code never gets out of
this require statement”.
I should have said ‘the interpreter never …’

Ah, I understand what you mean now.

However, that doesn’t really matter. The call to #require shouldn’t
happen, because the method is supposed to be stubbed out.
You are making a lot of suppositions that are not obvious to us. Nowhere
in your pastie is your require call stubbed.

I’m not sure why the call to #require would need to be stubbed.

What I’m trying to say is that I’ve set a message expectation on
AdSenseHeavenParser#parse , which should prevent the method from being
called in the first place.

-Nick


#11

On Sun, May 24, 2009 at 3:25 PM, Rick DeNatale removed_email_address@domain.invalid
wrote:

puts ‘*** create_keywords_and_associate ***’
require ‘lib/adsense_heaven_parser’
parsed_list = AdSenseHeavenParser.parse keyword_list_contents

The controller method has the require and then calls parse.

Yup! But in my specs, when the controller method calls #parse , the
stub should consume the method call.

One thing which strikes me is that if Rails naming conventions were
being followed:

  1. the file name be lib/ad_sense_heaven_parser not lib/adsense_heaven_parser

Normally, the file would be named like that. However, the class
represents a service called “AdSense Heaven”, which doesn’t have a
space between “Ad” and “Sense”…or should that still cause the file
to be named “ad_sense_…”?

  1. the require wouldn’t be needed since it would be autoloaded.

I thought that everything in lib/ should be autoloaded. When I found
that lib/adsense_heaven_parser.rb wasn’t being autoloaded, I figured I
was wrong, and simply #require’d it in.

Perhaps the problem lies there somewhere.

That’s a good idea. I’ll look into it and let you know.

Thanks,
Nick


#12

On Sun, May 24, 2009 at 3:25 PM, Rick DeNatale removed_email_address@domain.invalid
wrote:

One thing which strikes me is that if Rails naming conventions were
being followed:

  1. the file name be lib/ad_sense_heaven_parser not lib/adsense_heaven_parser
  2. the require wouldn’t be needed since it would be autoloaded.

Perhaps the problem lies there somewhere.

Hi Rick. I finally had some time to fix this problem, and you were
spot on. I moved
lib/adsense_heaven_parser.rb
to
app/models/ad_sense_heaven_parser.rb
and everything’s smooth now.

Thanks for catching that!
-Nick


#13

On Sun, May 24, 2009 at 9:25 AM, Nick H. removed_email_address@domain.invalid
wrote:

you can see that the second line is “*** create_keywords_and_associate
***”. However, that string shouldn’t be printed if
AdSenseHeavenParser#parse is stubbed out.

I don’t know why the AdSenseHeavenParser call isn’t being stubbed, but I
see
no reason why that string shouldn’t be printed. You’re not stubbing
create_keywords_and_associate.

I would remove the .with call to see if AdSenseHeavenParser is just
receiving different arguments than you expected.

BTW, class methods are generally indicated with a .; instance methods
with a
#.

///ark