RSpec Stubbing Java Static Method ArgumentError - ruby-on-rails

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

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.

Why is fixture_file_upload not available in RSpec (without ActiveRecord)?

I'm trying to test a file upload using RSpec 3.7 in a Rails 5.2 app, and the simplest recommendation I've seen (several places, including this SO post) is to use fixture_file_upload - which looks great, except that it doesn't seem to be available in my app, and I don't know why.
The only thing I can think of is that our app is not using ActiveRecord, it's using MongoID. But ActiveRecord shouldn't be required to use these methods... they're totally unrelated. Is there another new "ActiveSomething" library in Rails 5 that I'm missing? (this app was upgraded from a Rails 4 app...)
To explain my problem more concretely, I've tried putting:
let(:file) { fixture_file_upload('invalid_csv.csv') }
in one of my contexts, and it raises an exception:
undefined local variable or method 'fixture_path' for #<RSpec::ExampleGroups::...>
I tried defining config.file_fixture_path as outlined here, and that raises it's own exception:
undefined method `file_fixture_path=' for #<RSpec::Core::Configuration::...>
Does this work at all? Clearly I'm missing something...
I've fixed this by including their module on the RSpec config block:
RSpec.configure do |config|
#...
config.include ActionDispatch::TestProcess::FixtureFile
#...
end
this worked for me
Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures/doc.pdf"))

and_call_original used with allow_any_instance_of is not working after rspec upgrade to 3.1.0

I had a code in rspec 2.14.1 like
allow_any_instance_of(AnyClass).to receive(:some_method).and_call_original
with a corresponding message expectation
expect_any_instance_of(AnyClass).to receive(:some_method)
The above worked fine in rspec 2.14.1. After upgrade to rspec 3.1.0, the above code no longer works. It fails on the message expectation that some_method is not called even once
However if I change the stub like
allow_any_instance_of(AnyClass).to receive(:some_method).and_return(value)
it works fine in rspec 3.1.0.
I just wanted to understand why using and_call_original with allow_any_instance_of fails after rspec upgrade.
I can see from this link that and_call_original is only supported on partial doubles.
Does that mean using allow_any_instance_of is not partial double?
and_call_original does actually work when used with allow_any_instance_of.
Refer the specs for any_instance which gives us an idea of different ways of mocking or to un-stub using and_call_original here.
To answer my question above, the way I was using message expectation is wrong. It should be:
allow_any_instance_of(AnyClass).to(
receive(:any_method).and_call_original
)
expect(AnyClass.new.any_method).to eq(:any_method_value)
I was trying to use expect_any_instance_of instead of expect which caused the issue.

After upgrade to Rails 4: Specs fail in combination while passing in isolation

I'm struggling with this for quite a while now: I'm trying to upgrade an app from Rails 3.2 to Rails 4. While on Rails 3.2 all specs are passing, they fail under certain conditions in Rails 4.
Some specs are passing in isolation while failing when run together with other specs.
Example Video
https://www.wingolf.org/ak-internet-files/Spec_Behaviour.mp4 (4 mins)
This example video shows:
Running 3 specs using :focus–––green.
Running them together with another spec–––two specs passing before now fail.
Running the 3 specs, but inserting two empty lines–––one spec fails.
Undo does not help when using guard.
focus/unfocus does not help.
Restarting guard does not help.
Running all specs and then running the 3 specs again does help and make them green again. But adding the other task makes two specs fail, again.
As one can see, some specs are red when run together with other specs. Even entering blank lines can make a difference.
More Observations
For some specs, passing or failing occurs randomly when run several times.
The behavior is not specific to one development machine but can be reproduced on travis.
To delete the database completely between the specs using database_cleaner does not help.
To Rails.cache.clear between the specs does not help.
Wrapping each spec in an ActiveRecord::Base.transaction does not help.
This does occur in Rails 4.0.0 as well as in Rails 4.1.1.
Using this minimal spec_helper.rb without spring or anything does not help.
Using guard vs. using bundle exec rspec some_spec.rb:123 directly doesn't make a difference.
This behavior goes for model specs, thus doesn't have to do anything with parallel database connections for features specs.
I've already tried to keep as many gems at the same version as in the (green) Rails-3.2 branch, including guard, rspec, factory_girl, etc.–––does not help.
Update: Observations Based on Comments & Answers
Thanks to engineerDave, I've inserted require 'pry'; binding.pry; into one of the concerning specs. Using the cd and show-source of pry, it was ingeniously easy and fun to narrow down the problem: Apparently, this has_many :through relation does not return objects when run together with other specs, even when called with (true).
has_many(:groups,
-> { where('dag_links.descendant_type' => 'User').uniq },
through: :memberships,
source: :ancestor, source_type: 'Group'
)
If I call groups directly, I get an empty result. But if I go through the memberships, the correct groups are returned:
#user.groups # => []
#user.groups(true) # => []
#user.memberships.collect { |m| m.group } # returns the correct groups
Has Rails changed the has many through behavior in Rails 4 in a way that could be responsible? (Remember: The spec works in isolation.)
Any help, insights and experiences are appreciated. Thanks very much in advance!
Code
Current master branch on Rails 3.2––all green.
Rails-4 branch––strange behavior.
The file/commit seen in the video––strange behavior.
All specs passing on travis for Rails 3.2.
Diff of the Gemfile.lock (or use git diff master..sf/rails4-minimal-update Gemfile.lock |grep rspec)
How to Reproduce
This is how one can check if the issue still exists:
Preparation
git clone git#github.com:fiedl/wingolfsplattform.git
cd wingolfsplattform
git checkout sf/rails4-minimal-update
bundle install
# please create `config/database.yml` to your needs.
bundle exec rake db:create db:migrate db:test:prepare
Run the specs
bundle exec rspec ./vendor/engines/your_platform/spec/models/user_group_membership_spec.rb
bundle exec rspec ./vendor/engines/your_platform/spec/models/user_group_membership_spec.rb:213
The problem still exists, if the spec :213 is green in the second call but is red when run together with the other specs in the first call.
Based on that you're using:
the should syntax
that you indicate you've upgraded recently (perhaps a bundle update?)
that your failure messages indicate a NilObject error.
Is something like this perhaps what is causing it?
https://stackoverflow.com/a/16427072/793330
Are you are calling an object in your test which hasn't been instantiated yet?
I think this might be an rspec 3 upgrade issue where should is deprecated.
Have you ruled out an rspec gem upgrade to the new rspec 3 syntax (2.99 or 3.0.0+) as the culprit?
"Remove support for deprecated expect(...).should. (Myron Marston)"
IMO this behavior would not be caused by a Rails 4 update as its centered around your test suite.
Update (with pry debug):
Also you could use the pry gem to get a window into what is going on in your specs.
Essentially you can put a big "stop" sign (similar to a debug break) right before the spec executes to get a handle on the environment at that point.
it {
require 'pry'; binding.pry
should == something
}
Although beaware sometimes these pry calls wreck havoc on guard's threading and you have to kill it with CTRL+Z and then kill -9 PID that shows.
Update #2: Looking at updated answer.
You might be running up against FactoryGirl issues based on your has_many issue
You may need to trigger a before action in your Factory to pre-populate the associated record. Although this could get messy, i.e. here be monsters, you can trigger after and before callbacks in your factory that will bring these objects into being.
after(:create) do |instance|
do stuff here
end

Rails + RSpec problem

I have just installed Rspec and Rspec-rails. When i try to run the test, it says:
rake aborted!
Command /opt/local/bin/ruby -I"lib" "/opt/local/lib/ruby/gems/1.8/gems/rspec-1.3.0/bin/spec" "spec/controllers/free_controller_spec.rb" --options "/Volumes/Trash/dev/app/trunk/spec/spec.opts" failed
Full log here: http://pastie.org/939211
However, my second "test" application with sqlite works with it. I think the problem is in my DB.
My ruby version is 1.8.7, i use mysql as database.
My files:
specs/spec_helper.rb
config/environment.rb
config/environments/test.rb
List of my gems
My test is just:
require 'spec_helper'
describe FreeController do
it "should respond with success" do
get 'index'
response.should be_success
end
end
I really can't understand the error, so i don't know how to fix it..
Additional question: should i use a fixtures and ActiveRecord, if i going to use Machinist for creating test data? What should i do to disable them?
From your error log:
/app/models/thread.rb:1: superclass mismatch for class Thread (TypeError)
Is your model named Thread? You might have a name collision. Ruby has built-in class named Thread. Try renaming your model.

Resources