RSpec any_args matcher failing with wrong number of arguments? - ruby

I've added the following allow statement to spec_helper.rb to fix an issue in my codebase where tons of specs had added expect().receive on the metrics class making tests brittle to new metrics calls in underlying classes.
allow(MetricsClass).to receive(:increment).with(any_args)
Unfortunately, I'm running in errors
ArgumentError:
Wrong number of arguments. Expected 1, got 2.
The function definition:
def self.increment(counter_name, by: 1, **tags)
The line in the code where this failure happens:
MetricsClass.increment("string", **info)
Info itself is a hash
puts info
{"class/method"=>true}
ruby 2.7.6
rspec 3.12.0
Relevant RSpec configuration:
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end

Related

Why does FakeFS break RSpec?

test_spec.rb: (from FakeFS example)
require 'fakefs/spec_helpers'
describe 'Test' do
include FakeFS::SpecHelpers
it 'should fail' do
expect(1).to eq(2)
end
end
describe 'Test2' do
it 'should fail' do
expect(1).to eq(2)
end
end
rspec spec/test_spec.rb returns superclass mismatch for class File for the first test and normal expected: 2 got: 1 in the second case. Matcher changing (e.g. be_kind_of(String)) does not affect the result. Why does this happen, and how can it be fixed?
ruby -v
ruby 2.4.0dev (2016-03-19 trunk 54188) [x86_64-linux]
I just had this issue, and the accepted answer did not help me.
But I did eventually solve the issue by adding the following line to the top of my spec_helper.rb:
require 'pp'
I have a .rspec file with the following line to ensure spec_helper is loaded always:
--require spec_helper
It is documented in the FakeFS readme that you need to require pp before fakefs in order to avoid this problem, but I did not require pp myself. It must have been required implicitly by some other gem I use*.
Thus by explicitly requiring pp before fakefs, my specs now run as they should.
* I suspect RSpec uses pp for pretty printing error messages, as I could cause the exception in the line expect(true).to eq false
Thanks #d.g for link to fakefs issue. Things that works:
Gemfile
gem 'fakefs', require: 'fakefs/safe'
spec/spec_helper.rb
require 'fakefs/spec_helpers'
RSpec.configure do |config|
config.include FakeFS::SpecHelpers, fakefs: true
end
test_spec.rb
require_relative 'spec_helper.rb'
describe 'Test', fakefs: true do
it 'should fail' do
expect(1).to be_kind_of(String)
end
end

All SauceLabs tests run with Capybara result in "Unnamed Ruby job" and no metadata

I'm setting up a standalone RSpec/Capybara test suite integrated with SauceLabs, but the instructions in the documentation don't seem to be working for me.
Here are the relevant parts of my spec_helper.rb:
require 'capybara'
require 'capybara/rspec'
require 'sauce/capybara'
Sauce.config do |config|
config[:browsers] = [
[ "OSX 10.10", "Safari", "8" ]
]
end
Capybara.default_driver = :sauce
And here's the feature (not_found_spec.rb):
feature 'Enroll: 404', :sauce => true do
before :each do
#nonexistent_curriculum = FactoryGirl.build :curriculum
#enroll = Enroll.new
end
context 'When I visit a page that does not exist' do
scenario 'I see a Not Found message' do
#enroll.go #nonexistent_curriculum
expect(#enroll.not_found).to be_visible
end
end
end
When I then run rspec, the specs run and pass, but no metadata of any kind is recorded. All I see on SauceLabs is "Unnamed Ruby job".
What am I missing?
When you run
bundle exec rake sauce:install:spec
it creates a sauce_helper.rb which is then typically required from the end of your rails_helper.rb or spec_helper.rb depending on what *_helper.rb files you have. It looks like you copied the Sauce config part from sauce_helper into your spec_helper but you haven't shown that you have
require "sauce"
in there which is in the generated sauce_helper. Without requiring "sauce" it may be that sauce/rspec/rspec.rb is not getting required which is where all the hooks into rspec for tests with sauce: true are set up.

Running rspec in Sinatra app just starts the server

I'm using rspec to test my Sinatra app. The app is super simple, and so are the tests, but when I run rspec from the CLI, it just starts the app server. I've never had this happen.
Here's what my spec_helper.rb looks like:
#spec/spec_helper.rb
require File.expand_path '../../app.rb', __FILE__
ENV['RACK_ENV'] = "test"
require 'rspec'
require 'rack/test'
set :environment, :test
set :run, false
set :raise_errors, true
set :logging, false
module RSpecMixin
def app
App.new
end
end
RSpec.configure do |config|
config.color_enabled = true
config.tty = true
config.formatter = :documentation
config.include Rack::Test::Methods
config.include RSpecMixin
end
And my spec is just
require 'spec_helper'
describe "My Sinatra Application" do
it "should allow accessing the home page" do
expect(1).to eq(1)
end
end
I can't get rspec to run.
What I've tried:
I've tried the recommendations in this Sinatra testing guide. Also the rspec Sinatra test recipe. In this blog post, the set :run, false looked promising, but no dice. Then I thought, I'll just define a rake task. Putting the rspec gem in the test group and setting the RACK_ENV to test. All these things just start the app server:
$ rake spec
[2014-03-08 22:06:38] INFO WEBrick 1.3.1
[2014-03-08 22:06:38] INFO ruby 2.0.0 (2013-02-24) [x86_64-darwin11.4.2]
== Sinatra/1.4.4 has taken the stage on 4567 for development with backup from WEBrick
[2014-03-08 22:06:38] INFO WEBrick::HTTPServer#start: pid=21538 port=4567
Halp?
Try removing the new() from your def app:
module RSpecMixin
def app
App
end
end
An other way to create your app for testing is something like this:
APP = Rack::Builder.parse_file('config.ru').first
module RSpecMixin
def app
APP
end
end
Obvious this works only if you use config.ru.
I found the answer. It's embarrassing, but I was switching back and forth between the modular and classic style deciding which I liked best, and I had left an errant App.run! call at the bottom of my app.rb file.

How to stub any instances for a given class using Rspec Mocks

The following code raises an error: undefined method 'any_instance' for String:Class
require 'rspec'
RSpec.configure do |config|
config.mock_with :rspec
end
describe String do
it 'stubs' do
String.any_instance.stub(:foo).and_return(1)
''.foo.should eq(1)
end
end
How can I include the Mocks module into the Class or Object class?
any_instance was recently added to rspec, so your example now works for me as it is with rspec 2.7.
Update for rspec 3:
The new way to do this is
allow_any_instance_of(String).to receive(:foo).and_return(1)
Here is more any_instance documentation: https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/any-instance
With RSpec Mocks in versions previous to 2.6.0, you cannot do it. However you can use any_instance with Mocha(as seen here) or in later versions of Rspec.
In your spec/spec_helper.rb
Make sure you have this line:
config.mock_with :mocha
uncommented.

Mocha Mock Carries To Another Test

I have been following the 15 TDD steps to create a Rails application guide - but have run into an issue I cannot seem to resolve. For the functional test of the WordsController, I have the following code:
class WordsControllerTest < ActionController::TestCase
test "should get learn" do
get 'learn'
assert_response :success
end
test "learn passes a random word" do
some_word = Word.new
Word.expects(:random).returns(some_word)
get 'learn'
assert_equal some_word, assigns('word')
end
end
In the Word class I have the following code:
class Word < ActiveRecord::Base
def self.random
all = Word.find :all
all[rand(all.size)]
end
end
When I run the tests, I experience the following error (shortened for brevity):
1) Failure: unexpected invocation: Word(...).random() satisfied expectations:
- expected exactly once, already invoked once: Word(...).random()
I have tried changing changing the order of the tests along with a multitude of other things, but time and time again I continue to receive the same test failure - that Word.random() has already been invoked.
I'm running Rails 3.0 beta 4 and Mocha 0.9.8. I've searched long and hard for a solution to my problem, but I can't seem to find it. I'm new to Ruby/Rails so am rather unfamiliar with the language and the frameworks.
Thanks in advance!
mocha needs to be loaded last. I struggled a lot with this problem too.
#Gemfile
group :test
gem 'mocha', '~>0.9.8', :require => false
...
end
and
test_helper.rb
....
#at the very bottom
require 'mocha'
I had the same problem, mocked functionality was not isolated to a test, it seems to be a problem with the load order of Mocha.
I had some issues getting Mocha to work with Rails3. I found a few stackoverflow posts regarding, but didn't stumble across the solution until I found a post on agoragames.com
Basically, in the Gemfile of your project, the require for Mocha should look like:
gem 'mocha', :require => false
Then in test/test_helper.rb, add a require line for mocha:
...
...
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'mocha'
class ActiveSupport::TestCase
...
...
I think the require line for mocha in the Gemfile means that you need to already have mocha installed as a gem, bundler won't take care of it for you.
How are you requiring mocha? Are you using bundler? It sounds a bit as if the mocha teardown hook isn't being called?
Additionally, it seems mocha_teardown is not being called with rails31. Mocks that are setup are never removed... (this additional hack fixes it)
class ActiveSupport::TestCase
def teardown
super
Mocha::Mockery.instance.teardown
Mocha::Mockery.reset_instance
end
end
Those solutions didn't work for me on their own, using Ruby 2.2.2, Rails 4.2.2, mocha 1.1.0, shoulda-context 1.2.1, factory_girl_rails 4.5.0 and a few more testing related gems.
What did it was also moving these two lines at the bottom of my test_helper.rb:
require 'mocha/setup'
require 'mocha/test_unit'
I also removed require 'test/unit'. It appears that mocha/test_unit already does that for me.

Resources