Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

mock_model not working in Rails >= 3.0.1 #266

Closed
TheVole opened this Issue · 7 comments

5 participants

@TheVole

I'm working through David's excellent RSpec book and appreciating every minute, but have come unstuck on p.339 on the Beta 16 edition with the use of mock_model. The code works well under Rails 3.0.0, but fails in different ways for all of the later versions of Rails 3.0.1 - 3.0.3.

The error is "Failure/Error: form.should have_selector(".... and the output seems to show the stubbed method failing to supply the test value.

@dchelimsky
Owner

Please post the code you are using and the full failure message you are getting (run with rspec spec -b). Thx.

@wilkerlucio

Im having same problem here... The stack while trying to render is:

4) products/new.html.erb renders new product form
   Failure/Error: render
   ActionView::Template::Error
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/whiny_nil.rb:48:in `method_missing'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/inputs/base.rb:120:in `lookup_action'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/inputs/base.rb:111:in `translate'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/components/labels.rb:63:in `label_translation'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/components/labels.rb:47:in `raw_label_text'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/components/labels.rb:31:in `label_text'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/components/labels.rb:27:in `label'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/components/label_input.rb:9:in `label_input'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/inputs/base.rb:44:in `block in render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/inputs/base.rb:42:in `each'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/inputs/base.rb:42:in `render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/form_builder.rb:90:in `input'
   # ./app/views/products/_form.html.erb:5:in `block in _app_views_products__form_html_erb___573609283582759969_2157160480__384823360170852962'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/helpers/capture_helper.rb:40:in `block in capture'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/helpers/capture_helper.rb:172:in `with_output_buffer'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/helpers/capture_helper.rb:40:in `capture'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/helpers/form_helper.rb:544:in `fields_for'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/helpers/form_helper.rb:320:in `form_for'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/action_view_extensions/form_helper.rb:62:in `block in simple_form_for'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/action_view_extensions/form_helper.rb:28:in `with_custom_field_error_proc'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/simple_form-1.2.2/lib/simple_form/action_view_extensions/form_helper.rb:61:in `simple_form_for'
   # ./app/views/products/_form.html.erb:1:in `_app_views_products__form_html_erb___573609283582759969_2157160480__384823360170852962'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/template.rb:135:in `block in render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `block in instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/template.rb:127:in `render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/partials.rb:333:in `render_partial'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/partials.rb:262:in `block in render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `block in instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/partials.rb:260:in `render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/partials.rb:378:in `_render_partial'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/test_case.rb:149:in `_render_partial'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/rendering.rb:31:in `render'
   # ./app/views/products/new.html.erb:3:in `_app_views_products_new_html_erb__1520829205447778304_2154677080_1894098061964617228'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/template.rb:135:in `block in render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `block in instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/template.rb:127:in `render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/rendering.rb:59:in `block in _render_template'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `block in instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.3/lib/active_support/notifications.rb:52:in `instrument'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/rendering.rb:56:in `_render_template'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/render/rendering.rb:26:in `render'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/actionpack-3.0.3/lib/action_view/test_case.rb:107:in `render'
   # ./spec/views/products/new.html.erb_spec.rb:12:in `block (2 levels) in <top (required)>'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:42:in `instance_eval'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:42:in `block (2 levels) in run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:81:in `call'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:81:in `with_around_hooks'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:39:in `block in run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:75:in `call'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:75:in `block in with_pending_capture'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:74:in `catch'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:74:in `with_pending_capture'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example.rb:38:in `run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:261:in `block in run_examples'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:257:in `map'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:257:in `run_examples'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/example_group.rb:231:in `run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:27:in `block (2 levels) in run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:27:in `map'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:27:in `block in run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/reporter.rb:12:in `report'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/command_line.rb:24:in `run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/runner.rb:55:in `run_in_process'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/runner.rb:46:in `run'
   # /Users/wilkersilva/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.1.0/lib/rspec/core/runner.rb:10:in `block in autorun'
@steveh

I'm also getting a failure for mock_model & Rails 3, but it's a different failure:

20) PostsController existing edit should not edit posts anonymously
   Failure/Error: @user1 = stub_model(User, :roles => [:member])
   undefined method `stub' for #<User:0x000001044321a0>
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:364:in `method_missing'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:46:in `method_missing'
   # ./spec/controllers/posts_controller_spec.rb:6:in `block (2 levels) in <top (required)>'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/hooks.rb:29:in `instance_eval'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/hooks.rb:29:in `run_in'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/hooks.rb:64:in `run_all!'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/hooks.rb:112:in `run_hook!'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/example_group.rb:176:in `eval_before_alls'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/example_group.rb:230:in `run'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/command_line.rb:27:in `block (2 levels) in run'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/command_line.rb:27:in `map'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/command_line.rb:27:in `block in run'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/reporter.rb:12:in `report'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/command_line.rb:24:in `run'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/runner.rb:55:in `run_in_process'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/runner.rb:46:in `run'
   # /Users/steve/.rvm/gems/ruby-1.9.2-p0/gems/rspec-core-2.2.1/lib/rspec/core/runner.rb:10:in `block in autorun'
@realistschuckle

[edit]
So, I tried versions of rails 3.0.x and rspec 2.x.y and they all failed. This may be a caused by ruby-1.9.2p0. I will try ruby-1.8.7 later and see what I get...
[/edit]

I, too, have experienced some difficulty completing David's exceptional RSpec/Cucumber book. The mock_model call seems to ignore calls to the stub method after marked with as_null_object.

I discovered this problem with mock_model on page 338, the code reproduced for your convenience.
require 'spec_helper'

describe 'messages/new.html.haml' do
  let(:message) do
    mock_model('Message').as_new_record.as_null_object
  end

  before do
    assign(:message, message)
  end

  it 'renders a form to create a message' do
    render
    rendered.should have_selector(
      'form',
      :method => 'post',
      :action => messages_path
    ) do |form|
      form.should have_selector('input', :type => 'submit')
    end
  end

  it 'renders a text field for the message title' do
    message.stub :title => 'the title'
    render
    rendered.should have_selector('form') do |form|
      form.should have_selector(
        'input',
        :type => 'text',
        :name => 'message[title]',
        :value => 'the title'
      )
    end
  end
end

When running rspec, I get the following error message (formatting of error from me) where the title message does not resolve to the string stubbed but to the nested example group:
1) messages/new.html.haml renders a text field for the message title
Failure/Error: form.should have_selector(
expected following output to contain a tag:





name="message[title]"
size="30"
type="text"
value="Message_#<RSpec::Core::ExampleGroup::Nested_1:0x00000102cbb670>">


However, when I change the original code to the following, everything runs fine:
require 'spec_helper'

describe 'messages/new.html.haml' do
  let(:message) do
    mock_model('Message').as_new_record
  end

  before do
    assign(:message, message)
  end

  it 'renders a form to create a message' do
    assign(:message, message.as_null_object)
    render
    rendered.should have_selector(
      'form',
      :method => 'post',
      :action => messages_path
    ) do |form|
      form.should have_selector('input', :type => 'submit')
    end
  end

  it 'renders a text field for the message title' do
    message.stub :title => 'the title'
    render
    rendered.should have_selector('form') do |form|
      form.should have_selector(
        'input',
        :type => 'text',
        :name => 'message[title]',
        :value => 'the title'
      )
    end
  end
end

I use the following environment
ruby-1.9.2p0
rails (3.0.3)
rspec (2.2.0)
rspec-core (2.2.1)
rspec-expectations (2.2.0)
rspec-mocks (2.2.0)
rspec-rails (2.2.1)

@dchelimsky
Owner

Update: I've found the source of this problem and will have a solution in the next release (probably within a week).

Before rspec-mocks-2.1, a double acting as_null_object would respond to any message, but would return false if you asked respond_to?(:something_it_does_not_know). This was fixed in rspec-mocks-2.1, but it introduced this bug with mock_model.

The problem in this case is that the Rails form helper asks the model if it responds to title_before_type_cast, to which it answers true, at which point the helper sends title_before_type_cast to the model, to which it responds with the crazy value you see in the failure message.

@dchelimsky
Owner

mock_model.respond_to?(xxx_before_type_cast) returns false

@realistschuckle

David Chelimsky, you're my hero!

Seriously, thank you.

This issue was closed.
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.