undefined method `mock_model after upgrading app to rails 3.0.10

609 views
Skip to first unread message

Stephen Bannasch

unread,
Sep 2, 2011, 8:15:38 PM9/2/11
to cu...@googlegroups.com
I'm in the midst of upgrading a rails 2.3.x app to 3.0.10 and I have an rspec controller_helper that mocks some expensive
objects and want to be able to use these mocks from my Cucumber feature step definitions:

This following step:

Given /^The default project and jnlp resources exist using mocks$/ do
generate_default_project_and_jnlps_with_mocks
end

https://github.com/concord-consortium/rigse/blob/rails3.0/features/step_definitions/default_project_and_jnlps_steps.rb

And it is calling the method named: generate_default_project_and_jnlps_with_mocks in an rspec controller helper here:

https://github.com/concord-consortium/rigse/blob/rails3.0/spec/support/controller_helper.rb#L156

But when I try and run one scenario:

$ bundle exec cucumber features/limit_access_to_routes.feature:19

I'm getting an undefined method `mock_model' for #<Cucumber::Rails::World error:

Given The default project and jnlp resources exist using mocks # features/step_definitions/default_project_and_jnlps_steps.rb:12
undefined method `mock_model' for #<Cucumber::Rails::World:0x0000010cbe35b8> (NoMethodError)
./spec/support/controller_helper.rb:90:in `generate_jnlps_with_mocks'
./spec/support/controller_helper.rb:159:in `generate_default_project_and_jnlps_with_mocks'
./features/step_definitions/default_project_and_jnlps_steps.rb:13:in `/^The default project and jnlp resources exist using
mocks$/'
features/limit_access_to_routes.feature:17:in `Given The default project and jnlp resources exist using mocks'

Here's mu env.rb:

https://github.com/concord-consortium/rigse/blob/rails3.0/features/support/env.rb

aslak hellesoy

unread,
Sep 3, 2011, 5:19:05 AM9/3/11
to cu...@googlegroups.com
What Cucumber-Rails and Cucumber versions are you on?
It looks like you didn't regenerate the cucumber support files with rails g cucumber:install

Aslak
 
--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To post to this group, send email to cu...@googlegroups.com.
To unsubscribe from this group, send email to cukes+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/cukes?hl=en.


Stephen Bannasch

unread,
Sep 3, 2011, 2:09:47 PM9/3/11
to cu...@googlegroups.com
At 10:19 AM +0100 9/3/11, aslak hellesoy wrote:
>What Cucumber-Rails and Cucumber versions are you on?

From Gemfile.lock:

cucumber (1.0.2)
builder (>= 2.1.2)
diff-lcs (>= 1.1.2)
gherkin (~> 2.4.5)
json (>= 1.4.6)
term-ansicolor (>= 1.0.5)
cucumber-rails (1.0.2)
capybara (>= 1.0.0)
cucumber (~> 1.0.0)
nokogiri (>= 1.4.6)

>It looks like you didn't regenerate the cucumber support files with rails g cucumber:install

I intended to ... but perhaps I missed something .. here's what I did:

I ran created a temporary separate branch and ran the following and had it write over all the existing files (realized later I could have used --force):

$ rails generate cucumber:install --rspec --spork

Then I saved copies of all the replaced files, switched back to the rails3.0 branch and copied them there.

Files that I copied in whole without any manual merge:

config/cucumber.yml
features/support/selectors.rb
features/step_definitions/web_steps.rb
lib/tasks/cucumber.rake
features/support/paths.rb

I then first started trying to run one one the simplest feature tests with features/support/env.rb also copied in whole -- whenthat didn't work I started adding in more of the original requires and various other attempts.

I realize now that I didn't need to create the temporary branch -- with git (and Gitx) it is trivial to both see and discard any of the changes or deletions -- so a simpler process would have been to just start in the rails3.0 branch and run:

$ rails generate cucumber:install --rspec --spork --force

You can see the actual changes in this view which compares the before and after for these commits:

https://github.com/concord-consortium/rigse/compare/891fd674...423f66

Stephen Bannasch

unread,
Sep 3, 2011, 2:53:50 PM9/3/11
to cu...@googlegroups.com
At 2:09 PM -0400 9/3/11, Stephen Bannasch wrote:
>Files that I copied in whole without any manual merge:
>
> config/cucumber.yml
> features/support/selectors.rb
> features/step_definitions/web_steps.rb
> lib/tasks/cucumber.rake
> features/support/paths.rb
>
>I then first started trying to run one one the simplest feature tests with features/support/env.rb also copied in whole -- whenthat didn't work I started adding in more of the original requires and various other attempts.
>
>I realize now that I didn't need to create the temporary branch -- with git (and Gitx) it is trivial to both see and discard anyof the changes or deletions -- so a simpler process would have been to just start in the rails3.0 branch and run:

>
> $ rails generate cucumber:install --rspec --spork --force
>
>You can see the actual changes in this view which compares the before and after for these commits:
>
> https://github.com/concord-consortium/rigse/compare/891fd674...423f66

hmmm ... my description was not accurate.

I just ran the following in the rails3.0 branch:

$ rails generate cucumber:install --rspec --spork --force

And here is the git diff output:

https://gist.github.com/cf56ac41dbed816a2167

So I did manually merge changes into web_steps.rb and paths.rb not that these should affect he missing method on mock_model.

Thinking about the more general issue however I now realized that I might want to keep changes I make to files like web_steps and paths.rb in separate files just so I don't have to think about this the next time I update cucumber.

Running my simplest feature scenario with the files generated by cucumber:install reports this error:

undefined local variable or method `generate_default_project_and_jnlps_with_mocks'

That make sense since I am not requiring spec_helper yet ...

What's the right way to pull in the rspec helpers at this point?

If I add the following to the Spork.prefork do block in env.rb:

require File.expand_path('../../../spec/spec_helper.rb', __FILE__)

I get the following error:

undefined method `mock_model' for #<Cucumber::Rails::World:> (NoMethodError)


./spec/support/controller_helper.rb:90:in `generate_jnlps_with_mocks'
./spec/support/controller_helper.rb:159:in `generate_default_project_and_jnlps_with_mocks'

So ... the step definition IS getting to my generate_jnlps_with_mocks method in my rspec controller_helper.rb ...

The

Given The default project and jnlp resources exist using mocks # features/step_definitions/default_project_and_jnlps_steps.rb:12

undefined local variable or method `generate_default_project_and_jnlps_with_mocks' for #<Cucumber::Rails::World:0x0000010c22e9f0> (NameError)

Stephen Bannasch

unread,
Sep 9, 2011, 4:28:39 PM9/9/11
to cu...@googlegroups.com
I created a very simple Rails 3.0.10 app from scratch with RSpec, Cucumber and Haml that shows the problem I am having
accessing mock_model from a Cucumber feature.

https://github.com/stepheneb/rails-3-0-rspec-cucumber


I have a spec helper that creates an instance variable that using mock_model:

spec/support/app_helper.rb

def generate_resource_with_mock
@resource ||= mock_model(Resource)
end

The spec/controllers/pages_controller_spec.rb spec successfully calls this method:

before(:each) do
generate_resource_with_mock
end

I can run this controller spec fine:

$ bin/rspec spec/controllers/pages_controller_spec.rb
................

Finished in 0.55373 seconds
16 examples, 0 failures

I have a Cucumber step helper: features/step_definitions/resource_mock_steps.rb that calls the spec app helper:

Given /^A default resource exist using an RSpec mock$/ do
generate_resource_with_mock
end

And when this is evaluated in features/manage_pages.feature

Given A default resource exist using an RSpec mock

I see this error generated:

Scenario: Register new page # features/manage_pages.feature:6
Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1
undefined method `mock_model' for #<Cucumber::Rails::World:0x00000102e44cd0> (NoMethodError)
./spec/support/app_helper.rb:3:in `generate_resource_with_mock'
./features/step_definitions/resource_mock_steps.rb:2:in `/^A default resource exist using an RSpec mock$/'
features/manage_pages.feature:7:in `Given A default resource exist using an RSpec mock'

Matt Wynne

unread,
Sep 9, 2011, 4:41:01 PM9/9/11
to cu...@googlegroups.com

If you want to use that method in a Cucumber scenario, you'll need to include Spec::Rails::Mocks in your World. Try this in your env.rb:

World(Spec::Rails::Mocks)

This will tell Cucumber to include that module in every scenario's world (the place where step definitions run). You might also need to require 'rspec/mocks' or somesuch - ask about that on the RSpec list if you can't figure it out.

cheers,
Matt

--
Freelance programmer & coach
Author, http://pragprog.com/book/hwcuc/the-cucumber-book (with Aslak Hellesøy)
Founder, http://relishapp.com
+44(0)7974430184 | http://twitter.com/mattwynne

Stephen Bannasch

unread,
Sep 9, 2011, 5:10:25 PM9/9/11
to cu...@googlegroups.com
At 9:41 PM +0100 9/9/11, Matt Wynne wrote:
>If you want to use that method in a Cucumber scenario, you'll need to include Spec::Rails::Mocks inyour World. Try this in yourenv.rb:
>
>World(Spec::Rails::Mocks)
>
>This will tell Cucumber to include that module in every scenario's world (the place where step definitions run). You might alsoneed to require 'rspec/mocks' or somesuch - ask about that on the RSpec list if you can't figure it out.


Hi Matt,
I added: World(RSpec::Rails::Mocks) and still get the same error:

Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1

undefined method `mock' for #<Cucumber::Rails::World:0x00000104d0d090> (NoMethodError)


./spec/support/app_helper.rb:3:in `generate_resource_with_mock'
./features/step_definitions/resource_mock_steps.rb:2:in `/^A default resource exist using an RSpec mock$/'
features/manage_pages.feature:7:in `Given A default resource exist using an RSpec mock'

You can see the entire env.rb here:

https://github.com/stepheneb/rails-3-0-rspec-cucumber/blob/master/features/support/env.rb

It seems the RSpec::Rails::Mocks aren't getting added/included ...

But I'm confused about what Workd() is?

Does it take a block?

Where is "World" described/documented?

I looked in these places:

http://cukes.info/
https://github.com/cucumber/cucumber/wiki/
http://rdoc.info/github/cucumber/cucumber/master/frames

aslak hellesoy

unread,
Sep 9, 2011, 6:50:39 PM9/9/11
to cu...@googlegroups.com
On Fri, Sep 9, 2011 at 10:10 PM, Stephen Bannasch <stephen....@deanbrook.org> wrote:
At 9:41 PM +0100 9/9/11, Matt Wynne wrote:
>If you want to use that method in a Cucumber scenario, you'll need to include Spec::Rails::Mocks inyour World. Try this in yourenv.rb:
>
>World(Spec::Rails::Mocks)
>

>This will tell Cucumber to include that module in every scenario's world (the place where step definitions run). You might alsoneed to require 'rspec/mocks' or somesuch - ask about that on the RSpec list if you can't figure it out.


Hi Matt,
I added: World(RSpec::Rails::Mocks) and still get the same error:
   Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1
     undefined method `mock' for #<Cucumber::Rails::World:0x00000104d0d090> (NoMethodError)

     ./spec/support/app_helper.rb:3:in `generate_resource_with_mock'
     ./features/step_definitions/resource_mock_steps.rb:2:in `/^A default resource exist using an RSpec mock$/'
     features/manage_pages.feature:7:in `Given A default resource exist using an RSpec mock'

You can see the entire env.rb here:

https://github.com/stepheneb/rails-3-0-rspec-cucumber/blob/master/features/support/env.rb

It seems the RSpec::Rails::Mocks aren't getting added/included ...

But I'm confused about what Workd() is?

Does it take a block?

Where is "World" described/documented?

I looked in these places:

 http://cukes.info/
 https://github.com/cucumber/cucumber/wiki/
 http://rdoc.info/github/cucumber/cucumber/master/frames

--
You received this message because you are subscribed to the Google Groups "Cukes" group.
To post to this group, send email to cu...@googlegroups.com.
To unsubscribe from this group, send email to cukes+un...@googlegroups.com.

Matt Wynne

unread,
Sep 10, 2011, 3:18:19 AM9/10/11
to cu...@googlegroups.com

On 9 Sep 2011, at 22:10, Stephen Bannasch wrote:

> At 9:41 PM +0100 9/9/11, Matt Wynne wrote:
>> If you want to use that method in a Cucumber scenario, you'll need to include Spec::Rails::Mocks inyour World. Try this in yourenv.rb:
>>
>> World(Spec::Rails::Mocks)
>>
>> This will tell Cucumber to include that module in every scenario's world (the place where step definitions run). You might alsoneed to require 'rspec/mocks' or somesuch - ask about that on the RSpec list if you can't figure it out.
>
>
> Hi Matt,
> I added: World(RSpec::Rails::Mocks) and still get the same error:
>
> Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1
> undefined method `mock' for #<Cucumber::Rails::World:0x00000104d0d090> (NoMethodError)

That's a different error!

You now need to do something like:

World(RSpec::Mocks)

Again, check the RSpec docs / mailing list for exactly the right module to use.

> ./spec/support/app_helper.rb:3:in `generate_resource_with_mock'
> ./features/step_definitions/resource_mock_steps.rb:2:in `/^A default resource exist using an RSpec mock$/'
> features/manage_pages.feature:7:in `Given A default resource exist using an RSpec mock'
>
> You can see the entire env.rb here:
>
> https://github.com/stepheneb/rails-3-0-rspec-cucumber/blob/master/features/support/env.rb
>
> It seems the RSpec::Rails::Mocks aren't getting added/included ...
>
> But I'm confused about what Workd() is?
>
> Does it take a block?
>
> Where is "World" described/documented?
>
> I looked in these places:
>
> http://cukes.info/
> https://github.com/cucumber/cucumber/wiki/
> http://rdoc.info/github/cucumber/cucumber/master/frames
>

> --
> You received this message because you are subscribed to the Google Groups "Cukes" group.
> To post to this group, send email to cu...@googlegroups.com.

> To unsubscribe from this group, send email to cukes+un...@googlegroups.com.


> For more options, visit this group at http://groups.google.com/group/cukes?hl=en.
>

cheers,

Stephen Bannasch

unread,
Sep 10, 2011, 2:20:23 PM9/10/11
to cu...@googlegroups.com
At 8:18 AM +0100 9/10/11, Matt Wynne wrote:
>On 9 Sep 2011, at 22:10, Stephen Bannasch wrote:
>
>> At 9:41 PM +0100 9/9/11, Matt Wynne wrote:
>>> If you want to use that method in a Cucumber scenario, you'll need to include Spec::Rails::Mocks inyour World. Try thisin yourenv.rb:

>>>
>>> World(Spec::Rails::Mocks)
>>>
>>> This will tell Cucumber to include that module in every scenario's world (the place where step definitions run). You might alsoneed to require 'rspec/mocks' or somesuch - ask about that on the RSpec list if you can't figure it out.
>>
>>
>> Hi Matt,
>> I added: World(RSpec::Rails::Mocks) and still get the same error:
>>
>> Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1
>> undefined method `mock' for #<Cucumber::Rails::World:0x00000104d0d090> (NoMethodError)
>
>That's a different error!
>
>You now need to do something like:
>
>World(RSpec::Mocks)
>

I think including RSpec::Rails::Mocks should include RSpec::Mocks already ...

Here's a **very** strange clue -- changing nothing and running the feature with the debugger enabled works:

* bin/cucumber -d -b features/manage_pages.feature

Here the error without the debugger enabled and with backtraces turned on:

$ bin/cucumber -b features/manage_pages.feature
Using the default profile...
Feature: Manage pages
In order to [goal]
[stakeholder]
wants [behaviour]

Scenario: Register new page # features/manage_pages.feature:6

Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1

undefined method `mock' for #<Cucumber::Rails::World:0x00000103b8cd48>(NoMethodError)
./rspec-expectations-2.6.0/lib/rspec/matchers/method_missing.rb:9:in `method_missing'
./actionpack-3.0.10/lib/action_dispatch/testing/assertions/routing.rb:175:in `method_missing'
./actionpack-3.0.10/lib/action_dispatch/testing/integration.rb:372:in `method_missing'
./rspec-rails-2.6.1/lib/rspec/rails/mocks.rb:89:in `mock_model'
./spec/support/app_helper.rb:3:in `generate_resource_with_mock'
./features/step_definitions/resource_mock_steps.rb:2:in `block in <top(required)>'

You can see that at line 89 when rspec/rails/mocks.rb:89 calls the RSpec::Mock 'mock' method the RSpec::Mocks module isn't in scope and the method_missing error is generated.

But ... executing it with the debugger enabled works (???):

$ bin/cucumber -d -b features/manage_pages.feature
Using the default profile...
Feature: Manage pages
In order to [goal]
[stakeholder]
wants [behaviour]

Scenario: Register new page # features/manage_pages.feature:6

Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1

Given I am on the new page page # features/step_definitions/web_steps.rb:44
When I fill in "Name" with "name 1" # features/step_definitions/web_steps.rb:60
And I fill in "Content" with "content 1" # features/step_definitions/web_steps.rb:60
And I press "Save" # features/step_definitions/web_steps.rb:52
Then I should see "name 1" # features/step_definitions/web_steps.rb:105
And I should see "content 1" # features/step_definitions/web_steps.rb:105

Scenario: Delete page # features/manage_pages.feature:15
Given the following pages: # features/step_definitions/page_steps.rb:1
| name | content |
| name 1 | content 1 |
| name 2 | content 2 |
| name 3 | content 3 |
| name 4 | content 4 |
When I delete the 3rd page # features/step_definitions/page_steps.rb:5
Then I should see the following pages: # features/step_definitions/page_steps.rb:12
| Name | Content |
| name 1 | content 1 |
| name 2 | content 2 |
| name 4 | content 4 |

2 scenarios (2 skipped)
10 steps (10 skipped)
0m0.018s

It will be hard to get clues when the problem disappears just because I enable the debugger!

Matt Wynne

unread,
Sep 12, 2011, 8:02:43 AM9/12/11
to cu...@googlegroups.com
On 10 Sep 2011, at 19:20, Stephen Bannasch wrote:

At 8:18 AM +0100 9/10/11, Matt Wynne wrote:
On 9 Sep 2011, at 22:10, Stephen Bannasch wrote:

At 9:41 PM +0100 9/9/11, Matt Wynne wrote:
If you want to use that method in a Cucumber scenario, you'll need to include Spec::Rails::Mocks inyour World. Try thisin yourenv.rb:

World(Spec::Rails::Mocks)

This will tell Cucumber to include that module in every scenario's world (the place where step definitions run). You might alsoneed to require 'rspec/mocks' or somesuch - ask about that on the RSpec list if you can't figure it out.


Hi Matt,
I added: World(RSpec::Rails::Mocks) and still get the same error:

  Given A default resource exist using an RSpec mock # features/step_definitions/resource_mock_steps.rb:1
    undefined method `mock' for #<Cucumber::Rails::World:0x00000104d0d090> (NoMethodError)

That's a different error!

You now need to do something like:

World(RSpec::Mocks)


I think including RSpec::Rails::Mocks should include RSpec::Mocks already ...

Why did you think that?

I've looked it up for you, and actually the module you need to include is this one:


So try:

World(Rspec::Mocks::ExampleMethods)


Here's a **very** strange clue -- changing nothing and running the feature with the debugger enabled works:

 * bin/cucumber -d -b features/manage_pages.feature

Using -d does not enable a debugger as you thought, it enables a 'dry run' which doesn't try to execute and of your steps. Hence it didn't hit your error. 

If you look closely at your output you'll see your steps have been skipped:

   2 scenarios (2 skipped)
   10 steps (10 skipped)
   0m0.018s

I had a look at your example code on github. What you're doing is fairly unorthadox: requiring the whole of spec_helper like that from your cukes is not normally a good idea, as you'll use RSpec quite differently in unit tests to how you do in acceptance tests.

I'm surprised you think you need to use mock objects in cucumber tests, it's not something I do unless I'm in a really tight corner. Still, at least you know how to do it now.

Stephen Bannasch

unread,
Sep 12, 2011, 6:42:02 PM9/12/11
to cu...@googlegroups.com
At 1:02 PM +0100 9/12/11, Matt Wynne wrote:
On 10 Sep 2011, at 19:20, Stephen Bannasch wrote:

At 8:18 AM +0100 9/10/11, Matt Wynne wrote:
On 9 Sep 2011, at 22:10, Stephen Bannasch wrote:

I think including RSpec::Rails::Mocks should include RSpec::Mocks already ...

Why did you think that?

I've looked it up for you, and actually the module you need to include is this one:

https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/spec_methods.rb

So try:

World(Rspec::Mocks::ExampleMethods)

Matt, thanks so much for taking the time to help.

I needed to include both of these modules in this order to get my feature to ruk:

  World(RSpec::Rails::Mocks, Rspec::Mocks::ExampleMethods)

Here's a **very** strange clue -- changing nothing and running the feature with the debugger enabled works:

 * bin/cucumber -d -b features/manage_pages.feature

Using -d does not enable a debugger as you thought, it enables a 'dry run' which doesn't try to execute and of your steps. Hence it didn't hit your error.

duh ...!

Thanks for that clarification!

now runs properly with mock_model.

Stephen Bannasch

unread,
Sep 12, 2011, 11:48:05 PM9/12/11
to cu...@googlegroups.com
At 1:02 PM +0100 9/12/11, Matt Wynne wrote:

>I had a look at your example code on github. What you're doing is fairly unorthadox: requiring the whole of spec_helper like that from your cukes is not normally a good idea, as you'll use RSpec quite differently in unit tests to how you do in acceptance tests.
>
>I'm surprised you think you need to use mock objects in cucumber tests, it's not something I do unless I'm in a really tight corner. Still, at least you know how to do it now.

Factories work but for some of the feature tests mocks work and the tests run more than three times faster (the data below is from the large legacy app we are updating to Rails 3.0.10):

Using factories to create project dependent resources:

$ time bin/cucumber features/limit_access_to_routes.feature

49 scenarios (49 passed)
220 steps (220 passed)
4m47.391s

real 5m12.813s
user 0m6.640s
sys 0m0.938s

Using mocks to create project dependent resources:

$ time bin/cucumber features/limit_access_to_routes.feature

49 scenarios (49 passed)
220 steps (220 passed)
1m4.321s

real 1m28.695s
user 0m6.174s
sys 0m0.716s

Reply all
Reply to author
Forward
0 new messages