Mock object in array is getting size called on it

Hi, I have this code:

def self.bulk_create_from_holly( params )
params.map do |param|
new( param )
end
end

That is testeb by this expectation:

it "should generate a new property with each set of params" do
  [ @params, @properties ].transpose.each do |(param, property)|
    Property.should_receive( :new ).with( param ).and_return( 

property )
end

  do_call
end

In it, @params and @properties are of the same size (they are generated
together). The objects in the @properties array are not mocked active
record
objects, but just plain old mocks (ie. mock( property1 ) ). This has to
be
so, as I am using a third party ar adapter that does not support the
rails
spec stubs & mocks.
In the spec, I am simply trying to assert that a new property should be
generated for each item in @params.
However, I am getting this message when I run the expectation:

NoMethodError in ‘Property.bulk_create_from_holly( params ) should
generate
a new property with each set of params’
undefined method size' for #<Proc:0xb72721b4@ ./spec/models/property_spec.rb:49> /home/doug/work/rails/neville/app/models/property.rb:20:inbulk_create_from_holly’
/home/doug/work/rails/neville/app/models/property.rb:19:in map' /home/doug/work/rails/neville/app/models/property.rb:19:inbulk_create_from_holly’
./spec/models/property_spec.rb:38:in `do_call’
./spec/models/property_spec.rb:52:
./script/spec:10:

As you can see, nowhere do I call size(), and so can only think that
this is
some bizarre internal thing.
Or I’m being really dumb & missing something obvious.
Can anyone spot where I’m going wrong, or maybe suggest a way around
this?
Cheers,
Doug.

On Fri, Jun 26, 2009 at 7:13 AM, doug livesey[email protected] wrote:

it "should generate a new property with each set of params" do

so, as I am using a third party ar adapter that does not support the rails
bulk_create_from_holly' /home/doug/work/rails/neville/app/models/property.rb:19:in map’
/home/doug/work/rails/neville/app/models/property.rb:19:in
bulk_create_from_holly' ./spec/models/property_spec.rb:38:in do_call’
./spec/models/property_spec.rb:52:
./script/spec:10:

As you can see, nowhere do I call size(), and so can only think that this is
some bizarre internal thing.

Why don’t you debug it and find out where the call is coming from? If
you’ve updated to rspec-1.2.7 you can do this:

prop1 = mock(property1)
prop1.stub(:size) { puts caller(0)[1]; 37 }

Then at least we’ll know what we’re dealing with :slight_smile:

Cheers, I’ll update, re-unpack gems, & report back.
Doug.

Why don’t you debug it and find out where the call is coming from?

I get:

/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:171:in
`call’

That block’s a very useful feature I was unaware of! :wink:
Doug.

Copying that (a-la monkey see, monkey do), I get:

/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:171:in
call' /home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:171:ininvoke_return_block’
/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:122:in
invoke' /home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:99:inmessage_received’
/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:142:in
`size’

On Fri, Jun 26, 2009 at 8:30 AM, doug livesey[email protected] wrote:

/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:142:in
`size’

Ah - so close!!! Try [1…10] - I’m pretty sure that the next line
will reveal our culprit, as that will show the code that is actually
calling the size method.

That’ll be:

/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:171:in
call' /home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:171:ininvoke_return_block’
/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:122:in
invoke' /home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:99:inmessage_received’
/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:142:in
size' /home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:162:ininvoke_consecutive_return_block’
/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:120:in
invoke' /home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:101:inmessage_received’
/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:142:in
new' /home/doug/work/rails/neville/app/models/property.rb:20:inbulk_create_from_holly’

Sorry for the delays – keep getting called away into other things!
& thanks,
Doug.

On Fri, Jun 26, 2009 at 8:15 AM, doug livesey[email protected] wrote:

Why don’t you debug it and find out where the call is coming from?

I get:

/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/message_expectation.rb:171:in
`call’

That block’s a very useful feature I was unaware of! :wink:

Yeah - it’s in the release notes, but I should really blog about it.
Maybe next year :slight_smile:

Anyhow - that’s the code that’s calling the block I asked you to put
in there :slight_smile: Doesn’t help much - try going back a few frames in the
stack:

prop1 = mock(property1)
prop1.stub(:size) { puts caller(0)[1…5]; 37 }

On Fri, Jun 26, 2009 at 9:36 AM, doug livesey[email protected] wrote:

/home/doug/work/rails/neville/vendor/gems/rspec-1.2.7/lib/spec/mocks/proxy.rb:142:in
`bulk_create_from_holly’
This last line is where you should look, if you haven’t already.

This last line is where you should look, if you haven’t already.

Cheers – that’s just the function I listed, though (if I understand you
aright).
There’s definitely nothing in my code calling size, and any rails calls
are
stubbed out in my before block, so my guess is that it is something to
do
with the way I have the expectation structured?
For curiosity’s sake, I’m going to try explicitly calling each element
in
the two arrays & see if that makes any difference – I’ll post back how
I
get on.
Cheers,
Doug.

Nope, same error – bizarrely, a stub call in the before block works
just
fine.

Property.stub!( :new ).and_return( *@properties )

Very confusing!

Think I may draw a line under this for now. The latest (& getting very
hacky) expectation looks like this:

it "should generate a new property with each set of params" do
  @params.reduce( Property.should_receive( :new ).ordered ) do

|expectation, param|
expectation.with( param )
end.
and_return( *@properties )

  do_call
end

which gives this error:

<Property(Table doesn’t exist) (class)> expected :new with
({:property_holly_id__c=>“10”}) but received it with
([{:property_holly_id__c=>“1”}], [{:property_holly_id__c=>“2”}],
[{:property_holly_id__c=>“3”}], [{:property_holly_id__c=>“4”}],
[{:property_holly_id__c=>“5”}], [{:property_holly_id__c=>“6”}],
[{:property_holly_id__c=>“7”}], [{:property_holly_id__c=>“8”}],
[{:property_holly_id__c=>“9”}])

This suggests mismatched arrays, but when I change the first line of the
expectation to this:

  @params[0..-2].reduce( Property.should_receive( :new ).ordered ) 

do
|expectation, param|

The error then is:

<Property(Table doesn’t exist) (class)> expected :new with
({:property_holly_id__c=>“9”}) but received it with
([{:property_holly_id__c=>“1”}], [{:property_holly_id__c=>“2”}],
[{:property_holly_id__c=>“3”}], [{:property_holly_id__c=>“4”}],
[{:property_holly_id__c=>“5”}], [{:property_holly_id__c=>“6”}],
[{:property_holly_id__c=>“7”}], [{:property_holly_id__c=>“8”}],
[{:property_holly_id__c=>“10”}])

Which suggests that the final item in @params that gets passed in is not
being read. A debug puts of the items as they are used in the method
shows
that all are, in fact, being used.
Damn’ed if I know! :wink:
Thanks again for all your input – I’ve now got blocks in stubs to play
with!
Doug.