Rspec stubbing results in Mocha errors - ruby-on-rails

Not quite sure what's going on here. I'm moving over some code from another project of mine and suddenly the same specs from before are generating errors in the new project. All the errors appear to revolve around calling the stub method. Here's an example test:
it "retrieves active workers from Redis" do
#monitor.should_receive(:monitor_running?).and_return(false)
REDIS.should_receive( :smembers ).with( 'leaderboard-workers' ).and_return( [] )
#monitor.perform
end
This works. However if I switch the first test line to this:
#monitor.stub(:monitor_running?).and_return(false)
I end up with the following error:
1) LeaderboardMonitor#perform retrieves active workers from Redis
Failure/Error: #monitor.stub(:monitor_running?).and_return(false)
Mocha::ExpectationError:
unexpected invocation: #<Mock:0x7fcc18c8bab8>.and_return(false)
satisfied expectations:
- allowed any number of times, not yet invoked: #<Mock:0x7fcc18c8bab8>.monitor_running?(any_parameters)
# ./spec/workers/leaderboards/leaderboard_monitor_spec.rb:58:in `block (3 levels) in <top (required)>'
I'm not quite sure what's going on here. Is this an issue with Mocha overriding the stub method? How do I work around this?!?!?

I don't know what version of mocha you are using. Have you tried something like
#monitor.expects(:monitor_running?).returns(false).at_least_once

Related

Rails Engine - RSpec tests

I my main rails project I have mounted a engine of common code which does common tasks like currency conversion.
I can reference the methods in this common engine like this:
MyCommon::CurrencyHelper.convert_to_currency
This works fine in the project code, but does not seem to be working when I change the RSpec tests to point to the common methods.
The tests fail as it cannot find the common methods:
NoMethodError: undefined method `convert_to_currency' for MyCommon::CurrencyHelper:Module
./spec/helpers/application_helper_spec.rb:211:in `block (3 levels) in <top (required)>'
Do I need to do something else?
If by "I change the RSpec tests to point to the common methods" you mean that you are running the RSpec tests from engines/my_common directory (the engine's tests found in engines/my_common/spec) then you can find/reference your convert_to_currency method like this CurrencyHelper.convert_to_currency in your tests.
So for example, Stuff::BookingSlot.book_a_slot! (where Stuff is the engine) would be tested like this:
it 'book_a_slot! marks a slot as unavailable when a host is available' do
ai = FactoryGirl.create(:booking_slot, available: false, host_id: 1)
ai2 = ai.clone
ai2.update_attributes(available: true, host_id: 2)
BookingSlot.book_a_slot!
expect(ai2.reload.available).to eq false
end

rspec stub giving wrong number of arguments error

I am upgrading from rails 3.2.19 to rails 4.1.5. I am using rspec-rails 2.14.0.rc1.
With rails 4.1.5 all my tests are passing, except for a handful that use stub. The ones that are failing are of the form:
ENV.stub(:[]).with("ADWORDS_RUN").and_return("Yes")
Rails.stub(env: ActiveSupport::StringInquirer.new("production"))
Kernel.stub(:rand).and_return(2)
Each is returning ArgumentError: wrong number of arguments (1 for 2+). All were passing in rails 3.2.19. I have tried going back to rspec-rails 2.8.1, but same error. Also rails 4.0, but the error persists. The last error (stubbing :rand) does not occur when I run the whole test suite but does occur when I run the individual test file for that test. Here is an example test
it "should have google tracking code in production" do
Rails.stub(env: ActiveSupport::StringInquirer.new("production"))
get :home
response.body.should =~ /Google Analytics Tracking code/
end
and here is the output from the test:
Failure/Error: Rails.stub(env: ActiveSupport::StringInquirer.new("production"))
ArgumentError:
wrong number of arguments (1 for 2+)
# ./spec/controllers/pages_controller_spec.rb:107:in `block (4 levels) in <top (required)>'
Line 107 is the Rails.stub line.
Please let me know how to rectify this problem?
I did not manage to find the cause of this problem, but I did find a workaround. It was to change all the stub statements to the newer rspec allow syntax. So for example
Rails.stub(env: ActiveSupport::StringInquirer.new("production"))
becomes
allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))
I did this using rspec-rails 2.14.0.rc1. This fixed the problem.
Thank you for the comments, they either clarified my question or pointed me in the right direction.

Using "Bundle Update" in Rails produced bazillion errors on test

I'm trudging through this deeply error-prone tutorial on Ruby on Rails located here: http://ruby.railstutorial.org/ruby-on-rails-tutorial-book.
I've been working through a section about testing using rspec. Now, the instructions that this tutorial provided created a whole host of errors (deprecations, array issues, etc.) that filled up my page. After rummaging the internet for several hours, I decided to follow several suggestions to update all my gems.
Having updated my gems and attempted to perform this very basic test (the default test really), I got this whole pile of error that I couldn't begin to understand. All I can say is "please help".
Thank you.
> bundle exec rspec spec/requests/static_pages_spec.rb
Rack::File headers parameter replaces cache_control after Rack 1.5.
←[31mF←[0m
Failures:
1) StaticPages GET /static_pages works! (now write some real specs)
←[31mFailure/Error:←[0m ←[31mget static_pages_path←[0m
←[31mNameError:←[0m
←[31mundefined local variable or method `static_pages_path' for #<RSpec::
Core::ExampleGroup::Nested_1::Nested_1:0x5168040>←[0m
←[36m # ./spec/requests/static_pages_spec.rb:6:in `block (3 levels) in <top
(required)>'←[0m
Finished in 0.19901 seconds
←[31m1 example, 1 failure←[0m
Failed examples:
←[31mrspec ./spec/requests/static_pages_spec.rb:5←[0m ←[36m# StaticPages GET /st
atic_pages works! (now write some real specs)←[0m
If you upgraded all your gems to the latest, then one issue you probably have is your newer capybara gem no longer looks for your tests in 'spec/requests'. That test needs to be in 'spec/features' now. If there is no 'spec/features' just create it.
Also, capybara will need this line in your 'spec/spec_helper.rb' if it isn't already:
require 'capybara/rspec'

Rspec method not found when using model subfolders

Hello i am receiving this error:
spec/models/stores/persistent_spec.rb:6:in block (2 levels) in <top
(required)>': undefined methodexpect' for #
(NoMethodError)
Here is my setup. i have a class called Store located inside app/models
i have a class called Stores::Temporary < Store placed inside app/models/stores
I am trying to write tests for Temporary and they are failing with the error above
i have created temporary_spec.rb inside spec/models/stores and the code for it is the following:
require "spec_helper"
describe Stores::Temporary do
end
i am trying to write an expect to raise_error statement.
I have also tried 5.should == 5 which results with no available test being detected inside this file. I am using guard to autorun the tests, so changes in the files are being detected (works correctly) and tests are rerun but appear as blank.
So after struggling with this for 2 hours i restarted the PC and it was working without changing anything... One of those stupid errors you just need to sorta sleep-over and retry.

Spork causing undefined method error in my Rails app?

I have a standard Rails 3.2 app with some weird behavior going on.
I can run rspec spec/ without spork running and all tests pass no problem.
Then I fire up spork and run the specs again. This time, every test that touches one of my mailers will fail with the same error:
Failures:
1) InvitationsController GET accept with non-matching token should redirect to the root path
Failure/Error: let!(:invitation) { Factory :invitation }
NoMethodError:
undefined method `invite' for InvitationMailer:Class
# ./app/models/invitation.rb:29:in `send_email'
# ./spec/controllers/invitations_controller_spec.rb:5:in `block (3 levels) in <top (required)>'
Then, just to make it all a little weirder, I can run individual directories or specs, with or without spork running, and everything passes no problem. e.g rspec spec/mailers or rspec spec/models.
Here is the method which I am being told is undefined:
class InvitationMailer < ActionMailer::Base
default from: APP_CONFIG[:default_from]
def invite(invitation)
#invitation = invitation
mail(to: #invitation.recipient_email, subject: "the subject")
end
end
Any ideas what could be happening?
After spending some time tweaking Spork, I think it is possible to fix this.
For some reason, Spork is not loading the InvitationMailer file. So, the one thing you can do is require it within the Spork.each_run do block.
Also, here is the process I have used to diagnose Spork issues:
Move everything in the spec helper except for require 'spork' to inside the Spork.prefork do block. Make sure there are no errors. Use time to see how fast.
Move some code into the Spork.each_run do block.
Check to see if the the error happens. Use time to see how fast the tests run.
See if the error occurs. If so, then move some code back to pre_fork.
Keep moving stuff around until you figure out what needs to be in the prefork block and how much faster it runs.
This process was explained in this RailsCast.

Resources