[rspec-users] Problems with mock assigned to a constant

Matt Lins mattlins at gmail.com
Fri Jul 25 01:34:05 EDT 2008


On Fri, Jul 25, 2008 at 12:25 AM, Scott Taylor
<mailing_lists at railsnewbie.com> wrote:
>
> On Jul 25, 2008, at 1:15 AM, Matt Lins wrote:
>
>> On Thu, Jul 24, 2008 at 11:47 PM, Scott Taylor
>> <mailing_lists at railsnewbie.com> wrote:
>>>
>>> On Jul 25, 2008, at 12:32 AM, Matt Lins wrote:
>>>
>>>> I suppose the way I'm defining the stubs, differs from what Dave is
>>>> doing in his example.
>>>>
>>>> I assumed that:
>>>>
>>>> MyModel = mock('MyModel Class', :count => 1)
>>>>
>>>> was the same as:
>>>>
>>>> MyModel.stub!(:count).and_return(1)
>>>
>>> Nope.  Not even close.  Here's an equivalent of the first form:
>>>
>>> Object.send :remove_const, :MyModel
>>> MyModel = <a mock object>
>>>
>>> and here's the second form:
>>>
>>> MyModel.instance_eval do
>>> def count
>>>  1
>>> end
>>> end
>>>
>>> (or:)
>>>
>>> MyModel.class_eval do
>>> class << self
>>>  def count; 1; end
>>> end
>>> end
>>>
>>> Scott
>>>
>>>
>>
>> But the stubs are defined the same way in both occurrences, no?
>>
>> MyModel = mock('MyModel Class', :count => 1)
>>
>> By passing {:count => 1} to +stubs_and_options+ I should have defined
>> stubs on the mock object.  I'm using it as a shortcut for this:
>>
>> MyModel = mock('MyModel Class')
>> MyModel.stub!(:count).and_return(1)
>>
>> If those example aren't doing the exact same thing I guess I'm a
>> little baffled (or maybe just need to go to sleep).
>
> The first one is redefining the constant 'MyModel'.  The second one is just
> redefining a class method (the constant isn't changing - it's remaining
> whatever it was before - say, a class)
>
>>
>>
>>>>
>>>>
>>>> But, I'm starting to think they are not.  I haven't looked at the
>>>> rSpec internals to verify, other than the parameter name:
>>>>
>>>> stubs_and_options+ lets you assign options and stub values
>>>> at the same time. The only option available is :null_object.
>>>> Anything else is treated as a stub value.
>>>>
>>>> So, is this problem?
>>>
>>> Yeah - so here are two related, but not equivalent ideas: mock objects,
>>> and
>>> stubs.  A stub is just a faked out method - it can exist on a mock object
>>> (a
>>> completely fake object), or on a partial mock (i.e. a real object, with a
>>> method faked out).  mock('My mock") is a mock object,
>>> MyRealObject.stub!(:foo) is a real object with the method foo faked out.
>>>
>>> What is the difference between a mock object and a fake object?  A mock
>>> object will complain (read: raise an error) any time it receives a
>>> message
>>> which it doesn't understand (i.e. one which hasn't been explicitly
>>> stubbed).
>>> A real object will work as usual.  (A null object mock is a special type
>>> of
>>> mock - one which never complains.  For now, you shouldn't worry about
>>> it).
>>>
>>
>> Ok, I get what you saying, but as I understand it I am explicitly
>> stubbing out the methods on the _mock_ object and it's still
>> complaining.  If +stubs_and_options+ isn't stubbing, then what is it
>> doing?
>
> That's right - the hash to the mock method is a shorthand.  So these two are
> equivalent:
>
> my_mock = mock('a mock')
> my_mock.stub!(:foo).and_return(:bar)
>
> AND:
>
> my_mock = mock("a mock", {:foo => :bar})
>
> Scott
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>

Ok, then would you still insist that:

This:

http://gist.github.com/2372

Should produce this:

# spec migration_spec.rb
.F

1)
Spec::Mocks::MockExpectationError in 'Migration should find the records'
Mock 'MyModel Class' received unexpected message :count with (no args)
./migration.rb:14:in `run'
./migration_spec.rb:19:

Finished in 0.009435 seconds

--------------------

And like I said earlier, this code passes both examples with FlexMock(
if you simply replace mock with flexmock and uncomment the code in
spec_helper, of course you need the flexmock gem)


More information about the rspec-users mailing list