Mocha's regexp_matches missing some times - ruby-on-rails

I'm having a hard time getting any consistant behavior from Mocha and the regexp_matches method. If autotest runs my entire test suite everything works fine. If I purposely cause the test containing the regexp_matches call to fail and then fix it I get a method_missing error on regexp_matches. If I then run the entire test suite again, everything is fine. The bigger problem is coming from Hudson (continuous integration). It runs the entire test suite but always says regexp_matches is missing and I don't know how to fix it.
My test:
test "if token is set during Account creation the long url should be created correctly" do
Account.any_instance.expects(:http_get).with("api.server.com", regexp_matches(%r(^http://.*/accounts/\d+/jobs$)))
account = Account.create name: "New Account", token: "NewToken"
end
The error:
test_if_token_is_set_during_Account_creation_the_long_url_should_be_created_correctly(AccountTest):
NoMethodError: undefined method `regexp_matches' for #<AccountTest:0x0000010162d0c0>
test/unit/account_test.rb:158:in `block in <class:AccountTest>'
I don't even know what other code to add here as I can't imagine what the cause is. For giggles I pasted require 'mocha' at the top of the test file but that didn't change anything.

I ran into this problem on a rails project when removing
require 'spec_helper'
I did this so that running the spec would not load the whole rails environment. This means that external dependencies have to be required or mocked. Mocha obviously needs to be required.
But even after specifying
require 'mocha'
I ran into the same method missing issue.
Ultimately, I solved it by including the parameter matchers module directly:
require_relative "../../../lib/some_class"
require "mocha"
include Mocha::ParameterMatchers
describe SomeClass do
it "should do things" do
...

Related

Compound expectations stopped working rspec

Recently my tests are started failing with following exception.
NoMethodError:
undefined method `and' for #<Capybara::RSpecMatchers::Matchers::HaveText:0x00007f97687dbe30>
Did you mean? end
My tests looks like
it "starts german but allows to be changed to english" do
within(".e-header") do
# german locale
expect(page).to have_content("Mein Anliegen").and not_have_content("My issue")
end
end
Rspec 3.10 documentation for compound expectations still supporting it. I am not sure why suddenly my tests started failing.
it looks like capybara will not include compound module if rspec expectations is not be defined (in other words, not require yet)
so try require "rspec/expectations" explicitly.
the reason:
it was due to the version range of RSpec we supported combined with the fact that a few people complained when we did because some people didn't want RSpec::Expectations. Most people don't run into this issue because they're using Capybara with rspec-rails.
A very similar error happened when I ran my test suite with Spring enabled:
undefined method `and' for #<Capybara::RSpecMatchers::Matchers::HaveSelector
The answer in the comment by Asad Ali helped, just added:
bundle add rspec-expectations --group test
And the specs work with Spring.

RSpec Stubbing Java Static Method ArgumentError

I am attempting to stub a Java static method in my specs for my JRuby class which imports some Java libraries. I get the following error for the method call:
Failure/Error: JCoDestinationManager.getDestination('properties')
ArgumentError:
Wrong number of arguments. Expected 0, got 1.
That's the JCo Java static method. I created a small spec file to try and isolate the issue:
require 'rails_helper'
describe SapClient do
let(:destination) { double(Java::ComSapConnJcoRt::RfcDestination) }
before do
allow(JCoDestinationManager).to receive(:getDestination).and_return destination
end
it 'can be created' do
c = SapClient.new
expect(c).to_not be_nil
end
end
If I add the with clause like so, I still get the same result.
allow(JCoDestinationManager).to receive(:getDestination).with('properties').and_return destination
The strange part to me is that I only encounter this project in rails. If I copy the code over to a Sinatra project and run these specs there, all is well. I created a new Rails project and a new Sinatra project and installed the same versions of RSpec, verified RSpec mocks were the same version, etc. and still saw the discrepancy in behavior.
When I throw in a pry and observe what happens when I just call
JCoDestinationManager.getDestination
With no arguments, I get the mock destination that I define. If I comment out the allow statement, I see a real RfcDestination get created.
While searching, only thing I saw that seemed close to what I'm observing here is from https://github.com/rspec/rspec-mocks/issues/919 but apparently the solution to this problem was a jruby issue that has since been fixed.
Rails Gemfile
Rails Gemfile.lock
Sinatra Gemfile
Sinatra Gemfile.lock

Intermittent ActiveRecord::RecordNotFound during Ruby on Rails Integration Tests

I have integration tests that are intermittently failing, and always with ActiveRecord::RecordNotFound errors. The error takes place inside the controller where a find call takes place given an ID from a fixture. It takes place in multiple controllers, though. I never see this behaviour while navigating the site, but I'd say the tests fail about 30-50% of the time. Running the test again after a failure seems to fix the problem.
If I load the fixtures manually into the development database, the ID that doesn't seem to be found is indeed present inside the tables.
I haven't been able to find much info on people having the same problem... any ideas?
UPDATE: Here are the contents of test_helper.rb
ENV["RAILS_ENV"] = "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'capybara/rails'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
fixtures :all
# Add more helper methods to be used by all tests here...
end
# Transactional fixtures do not work with Selenium tests, because Capybara
# uses a separate server thread, which the transactions would be hidden
# from. We hence use DatabaseCleaner to truncate our test database.
DatabaseCleaner.strategy = :truncation
class ActionDispatch::IntegrationTest
# Make the Capybara DSL available in all integration tests
include Capybara::DSL
# Make the Capybara Email DSL available in all integration tests
include Capybara::Email::DSL
# Stop ActiveRecord from wrapping tests in transactions
self.use_transactional_fixtures = false
# Switch to selenium as the default driver for JS support
Capybara.default_driver = :selenium
# Only click on visible links!
Capybara.ignore_hidden_elements = true
teardown do
DatabaseCleaner.clean # Truncate the database
Capybara.reset_sessions! # Forget the (simulated) browser state
Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
end
end
UPDATE Here are the results of running the same test 5 times in a row. I ran the tests, waited until they finished, and then immediately ran them again with the command rails test:integration. NOTE: The E and F that are consistent throughout the tests are actually test errors -- I'm working on fixing those. For example, the second test run-through was "correct", but the first showed the spurious error.
..E......E..........F.
.........E..........F.
..E......E..........F.
..E......E..........F.
..E....E.E..........F.
The errors do occur across two separate tables -- they're not trying to find the same record. But it does appear to be only a subset of the tests that have this issue...
UPDATE Here's what the actual error looks like in the test results:
1) Error:
test_browsing_user_snops(BrowseStoriesTest):
ActiveRecord::RecordNotFound: Couldn't find User with id=980190962
/home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/relation/finder_methods.rb:341:in `find_one'
/home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/relation/finder_methods.rb:312:in `find_with_ids'
/home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/relation/finder_methods.rb:107:in `find'
/home/myuser/.rvm/gems/ruby-1.9.3-p286/gems/activerecord-3.2.9/lib/active_record/querying.rb:5:in `find'
/home/myuser/Projects/myproject/app/controllers/users_controller.rb:18:in `show'
...
Notice that the error appears when the controller tries to find a record. The relevant line is actually #user = User.find(params[:id]). It occurs with other models also, not just the users controller and not just the User model.
I'm concerned that there may be a delay during the truncation of data and the speed in which Capybara is driving the web browser which sometimes may result in identity column values starting at an unexpected value (i.e., 7 for record #1 - when you expect 1, because that identity generator has not yet been reset). I have no evidence that this is the case but its my best guess.
Take at look at item #3 at this URL. This is a pretty straight-forward hack, set use_transactional_fixtures to true and monkeypatch ActiveRecord by pasting that code into your test_helper.rb. This could help in eliminating any intermittent disk IO problems that could be a potential problem.
Another thing you can try is restricting your SQLite test database by setting the filename for that database to :memory: in your database.yml file. This should accomplish the same thing as above - eliminate spurious disk IO that may be causing these intermittent issues.

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.

Tests pass using "autotest" but not "rake test" using Authlogic

My tests fail when doing "rake test:functionals" but they pass consistently using autotest.
The failing tests in question seems to be related to Authlogic not logging in the user properly when using rake.
For facilitating signing in a user in tests, I have a test helper method as follows:
class ActionController::TestCase
def signin(user, role = nil)
activate_authlogic
UserSession.create(user)
user.has_role!(role) if role
end
end
The above method is used to signin a user
My stack is shoulda/authlogic/acl9/factory_girl/mocha
The reason why I suspect Authlogic being the issue is the failing tests look like this:
54) Failure:
test: A logged in user PUT :update with valid data should redirect to user profile. (UsersControllerTest)
[/var/lib/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/action_controller/macros.rb:202:in `__bind_1251895098_871629'
/var/lib/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `call'
/var/lib/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `test: A logged in user PUT :update with valid data should redirect to user profile. ']:
Expected response to be a redirect to <http://test.host/users/92> but was a redirect to <http://test.host/signin>.
55) Failure:
test: A logged in user PUT :update with valid data should set the flash to /updated successfully/i. (UsersControllerTest)
[/var/lib/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/assertions.rb:55:in `assert_accepts'
/var/lib/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/action_controller/macros.rb:41:in `__bind_1251895098_935749'
/var/lib/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `call'
/var/lib/gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `test: A logged in user PUT :update with valid data should set the flash to /updated successfully/i. ']:
Expected the flash to be set to /updated successfully/i, but was {:error=>"You must be signed in to access this page"}
Autotest reads all test files upfront AFAIR (it does so with RSpec, I haven't been using plain tests for a long time now so I may be wrong).
To properly test controllers you need to call activate_authlogic in your setUp method. This is probably done automatically (globally) for integration tests.
Since autotest reads all tests it runs this global setUp and functional tests pass. When you run only functional tests authlogic is not enabled and your tests fail.
I'm not sure about where your problem lies, but I suggest you use Cucumber for testing controllers and user interaction instead of unit tests/rspec. The reason for that is that you exercise your entire app, including the authentication and authorization code you have.
Clearly the user is not getting logged in. Seems like Bragi Ragnarson might be on to something.
Here are some other things to isolate the problem:
Understand if the test is incomplete or relying on some side-effect of autotest. Run the test by itself:
ruby test/functionals/users_controllers_test.rb
Presumably that won't work. If it doesn't, there's some global code that is getting invoked for non functional tests by autotest. It's probably code setting in the test/integration or test/units directories, or one of their requires there.

Resources