[rspec-users] 2nd attempt at mocking and stubbing

David Chelimsky dchelimsky at gmail.com
Sat Sep 6 15:58:31 EDT 2008


On Sat, Sep 6, 2008 at 2:32 PM, Nick Hoffman <nick at deadorange.com> wrote:
> On 2008-09-05, at 18:22, Jonathan Linowes wrote:
>>
>> On Sep 5, 2008, at 5:44 PM, Nick Hoffman wrote:
>>
>>> Property.stub!(:find).and_return mock_property1, mock_property2
>>
>> try
>> Property.stub!(:find).and_return( [mock_property1, mock_property2] )
>
> Thanks Jonathan and David. That was a silly mistake.
>
> With that fixed, a new question has popped up. My specs for the method I
> previously mentioned are now:
>
> 185   describe '#add_properties' do # {{{
> 186     it 'should add properties to the map' do
> 187       map               = RentalMap.new @map_name, @latitude, @longitude
> 188       mock_property1    = mock 'property'
> 189       mock_property2    = mock 'property'
> 190       marker1_contents  = 'Some contents for the first property'
> 191       marker2_contents  = 'Some contents for the second property'
> 192
> 193       Property.stub!(:find).and_return [mock_property1, mock_property2]
> 194       map.stub!(:add_marker).and_return "Doesn't matter"
> 195
> 196       mock_property1.stub!(:address  ).and_return '400 Bloor Street'
> 197       mock_property1.stub!(:latitude ).and_return 12.34
> 198       mock_property1.stub!(:longitude).and_return 56.78
> 199       mock_property2.stub!(:address  ).and_return '500 Bloor Street'
> 200       mock_property2.stub!(:latitude ).and_return 12.45
> 201       mock_property2.stub!(:longitude).and_return 56.89
> 202       map.stub!(:generate_marker_contents).twice.and_return
> marker1_contents, marker2_contents
> 203
> 204       map.should_receive(:add_marker).with mock_property1.address,
> mock_property1.latitude, mock_property1.longitude, marker1_contents
> 205       map.should_receive(:add_marker).with mock_property2.address,
> mock_property2.latitude, mock_property2.longitude, marker2_contents
> 206
> 207       map.add_properties
> 208     end
> 209   end # }}}
>
> However, lines 190 and 191 feel a bit like I'm setting up fixture data. But
> the only alternative that I can think of will fail:
> -Comment out lines 190 and 191.
> -On line 202, replace "marker*_contents" with the strings on lines 190 and
> 191.
> -Lines 204 and 205 will have to call #generate_marker_contents for the last
> argument.
> -Lines 204 and 205 will then consume the two calls to
> #generate_marker_contents that I expect on line 202.
>
> Can anyone suggest a better/different way of doing this?

Well, without changing the underlying semantics, you can clean up the
syntax a bit like this:

  mock_property1 = stub('property', :address => '400 Bloor Street',
:latitude => 12.34, :longitude => 56.78)

Of course, that doesn't address your question :)

Here's another thought that doesn't answer your question - this line
in the code:

  add_marker p.address, p.latitude, p.longitude, generate_marker_contents(p)

is resulting in a situation where you have to do a lot of setup in
order to isolate the object under test. The line exhibits the Feature
Envy Code Smell, which is the odor emitted by one object depending on
another object's data.

If I were coding by example, I'd probably start w/ a simple example like this:

describe '#add_properties' do
  it 'should add one property to the map' do
    map = RentalMap.new @map_name, @latitude, @longitude
    mock_property = mock 'property'
    Property.stub!(:find).and_return [mock_property]

    mock_property.should_receive(:add_marker_to).with(map)

    map.add_properties
  end
end

This defines how I'd like to be able to "talk" to the Property, and
results in an implementation like this:

  p.add_marker_to(map)

Now all the additional behaviour is pushed to the Property, for which
you can write code examples with the details of its own data rather
than having to stub so much of its data for use in the current
example.

That all make sense?
David



>
> Thanks,
> Nick
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list