4

I want to stub out the space_available_mb method in SubmissionsController so that it returns 5. This doesn't work. It returns the correct space on the real hard disk.

if space_available_mb is commented out, an expectation error is thrown, which means should_receive works correctly. However, it doesn't return 5, but the real number, which means and_return fails for some reason.

Further debugging reveals that and_return is actually called, but only after the method has run and returned the real number.

Scenario: Hard Disk Space is low on new submission
  Given I am on the new_submission page
  And hard disk space is low
  Then I should see "Low disk space!"

Given /^hard disk space is low$/ do
  SubmissionsController.should_receive(:space_available_mb).and_return(5)
end

class SubmissionsController < ApplicationController
  include FileManager

  def new
    space = space_available_mb
    ...
  end
end

module FileManager
  def space_available_mb
    ...
  end
end
siamii
  • 23,374
  • 28
  • 93
  • 143
  • does [this](https://github.com/cucumber/cucumber/tree/master/examples/rspec_doubles/features) help you? – farnoy Feb 22 '12 at 17:33
  • 1
    @farnoy that explains how to create a mock object. in this case, I need to stub a controller method. – siamii Feb 23 '12 at 08:44
  • Note that this is usually not a good idea. Cucumber should usually test the full stack. Your use case—where you're essentially trying to stub an external service—is about the only time that this is advisable. – Marnen Laibow-Koser Aug 22 '13 at 20:59

1 Answers1

5

Depending on a mock framework, the syntax differs, but what you're trying to accomplish is stubbing a method on any instance of your controller. In RSpec, you have this. So according to your attempts:

Given /^hard disk space is low$/ do
  SubmissionsController.any_instance.should_receive(:space_available_mb).and_return(5)
end

If you plan to use any other mock frameworks, there's bound to be a method like this any_instance of RSpec's.

farnoy
  • 7,356
  • 2
  • 20
  • 30
  • unfortunately, any_instance doesn't seem to make a difference. Interestingly, It is reported that the method is called, because if I comment out the call, a MockExpectationError is thrown. However, the return value is not substituted. (doesn't return 5) – siamii Feb 23 '12 at 16:58
  • 1
    it turns out that `any_instance` indeed was one of the issues. The other issue was that the `hard disk is low` step should come before the `I'm on the new_submission page` – siamii Feb 23 '12 at 17:42
  • Can you `puts SubmissionsController.new.space_available_mb` for both the solution above and `SubmissionsController.any_instance.stub(:space_available_mb).and_return(5)` ? – farnoy Feb 23 '12 at 17:45
  • I'm using break points. `should_receive` and `stub` both work fine, only the former also requires the `space_available_mb` to be called – siamii Feb 23 '12 at 17:51
  • so everything that you asked about was covered here? – farnoy Feb 23 '12 at 18:09
  • as I said, the issue was http://stackoverflow.com/questions/9390220/how-to-stub-a-method-in-cucumber/9414647#comment11904758_9414647 . The solution for the problem is that I should have used `any_instance` and that I should have put the `hard disk is low` step before the `I am on the new submission page`, because originally, the `new` method in the `SubmissionsController` was executed before the stubbing took place. – siamii Feb 24 '12 at 02:53
  • 1
    I'm getting undefined method `any_instance_recorder_for' for nil:NilClass and this link http://stackoverflow.com/a/18753331/1123985 isn't helping. I'm trying to stub an active record object in each scenario. Tried in rspec 2.14 and rspec 2.99. – davidtingsu Dec 10 '13 at 16:26
  • 4
    @davidtingsu you need to require rspec doubles. Put the following in your env.rb file for cucumber: `require 'cucumber/rspec/doubles'` – sma Apr 11 '14 at 00:52