Skip to content

mocking a model with a description attribute #437

Closed
dchelimsky opened this Issue Sep 8, 2011 · 8 comments

3 participants

@dchelimsky
RSpec member

(Reported by @jacobat in rspec-mocks)

I have an issue where when I have a model with a description attribute and mock that with mock_model I get an interesting error.

To reproduce:

rails new testproject
cd testproject
echo 'gem "rspec-rails"' >> Gemfile
bundle install
rails g rspec:install
rails g model location description:text
rake db:migrate

Add an example to location_spec.rb with this code:

Location.should_receive(:bar).with(mock_model(Location))

And run rake spec.

This results in:

Mock "Location_1001" received unexpected message :description with (no args)

It would be nice if instead it said something like:

Location did not recieve message :bar with arguments...
@dchelimsky
RSpec member

Per the issue from which this was copied:

Culprit is interplay between https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/error_generator.rb#L82 and https://github.com/rspec/rspec-rails/blob/master/lib/rspec/rails/mocks.rb#L115-117. When mock_model checks the real model's columns and returns true to respond_to?, it should also stub that method.

@jacobat
jacobat commented Sep 8, 2011

I actually tried stubbing the description method on the mocked model without any luck. If that has any relevance.

@iafonov
iafonov commented Dec 7, 2011

Hi, I had similar issues caused by (imho) inconsistent mock_model's respond_to? behavior. I think that if you call respond_to? method and it returns true you can rely on it and call this method. In my fix if respond_to? finds column and there is no predefined stub for it it will stub it. Also this fixes issue with description column described by @jacobat.

@dchelimsky dchelimsky closed this in 9a23ba1 Dec 7, 2011
@dchelimsky dchelimsky added a commit that referenced this issue Dec 7, 2011
@dchelimsky dchelimsky Changelog for #437 88137f2
@dchelimsky
RSpec member

@iafonov - I merged that too quickly - the implementation actually introduces a bug:

thing = mock_model(Thing, :name => "The Thing")
thing.name # => "The Thing"
thing.respond_to?(:name)
thing.name # => nil

Wanna take a crack at fixing that? Here are some examples that should all pass:

        it "stubs column accessor (with string)" do
          @model.respond_to?("column_a")
          @model.column_a.should be_nil
        end
        it "stubs column accessor (with symbol)" do
          @model.respond_to?(:column_a)
          @model.column_a.should be_nil
        end
        it "does not stub column accessor if already stubbed in declaration (with string)" do
          model = mock_model(MockableModel, "column_a" => "a")
          model.respond_to?("column_a")
          model.column_a.should eq("a")
        end
        it "does not stub column accessor if already stubbed in declaration (with symbol)" do
          model = mock_model(MockableModel, :column_a => "a")
          model.respond_to?("column_a")
          model.column_a.should eq("a")
        end
        it "does not stub column accessor if already stubbed after declaration (with string)" do
          @model.stub("column_a" => "a")
          @model.respond_to?("column_a")
          @model.column_a.should eq("a")
        end
        it "does not stub column accessor if already stubbed after declaration (with symbol)" do
          @model.stub(:column_a => "a")
          @model.respond_to?("column_a")
          @model.column_a.should eq("a")
        end
@iafonov
iafonov commented Dec 7, 2011

I'll take a look at it, I think I know the cause.

@dchelimsky
RSpec member

@iafonov - great. TIA.

@iafonov iafonov added a commit to iafonov/rspec-rails that referenced this issue Dec 7, 2011
@iafonov iafonov Take 2 on stubbing attribute accessor after respond_to? call on mocke…
…d model. Fixes #437.
9f86140
@iafonov
iafonov commented Dec 7, 2011

I have reworked respond_to? method to dynamically check whether method was stubbed. I have added your examples to spec and it passes. I'm new to rspec internals so I'd be glad to get any feedback. The thing that I'm worried about is how I'm getting list of stubbed methods for an object. I have quickly reviewed rspec sources but I haven't found a better way. Please let me know if there is a better way to do it exists.

Thanks.

@dchelimsky dchelimsky added a commit that referenced this issue Dec 8, 2011
@dchelimsky dchelimsky Implement method_missing on mock model's proxy object rather than
stubbing upon respond_to?

- #437
8a0a6f5
@dchelimsky
RSpec member

@iafonov - I added method_missing instead - feels less invasive than digging into method double internals. Not that the whole thing isn't already pretty invasive :)

@ndbroadbent ndbroadbent pushed a commit to ndbroadbent/rspec-rails that referenced this issue Dec 21, 2011
@iafonov iafonov Take 2 on stubbing attribute accessor after respond_to? call on mocke…
…d model. Fixes #437.
e242279
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.