RSpec error: 'but it does not respond to `include?`' - ruby-on-rails

I am running the following rspec test
expect(City.first.city_openings('2014-05-01', '2014-05-05')).to include(#listing2,#listing3)
I am getting this result
This is confusing to me because it seems that my result does in fact include the right values. But rspec says that my result "does not respond to include?" Any ideas on how to fix this? I don't see much about it anywhere.

Your method city_openings return true and not a array.
TrueClass is not iterable with include? method.
See the documentation here
https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/include-matcher
https://relishapp.com/rspec/rspec-expectations/v/3-7/docs/built-in-matchers/match-matcher

Related

how to stub a method for a specific argument in Rspec

I'm trying to stub a method like so:
allow(Flipper).to receive(:enabled?).with(:premium_plus_features_beta).and_return(false)
but when it hits a different argument - it gives me an error like this:
#<Flipper (class)> received :enabled? with unexpected arguments
expected: (:premium_plus_features_beta)
got: (:non_advertiser_profile_amp, {:lawyer_id=>4469860})
Diff:
## -1,2 +1,2 ##
-[:premium_plus_features_beta]
+[:non_advertiser_profile_amp, {:lawyer_id=>4469860}]
I normally don't stub this much but why when I explicitly tell it the arguments, why is it erroring on different arguments? They are obviously not the same. Is this just some syntax issue?
edit 1
I tried this but doesn't work
https://makandracards.com/makandra/30543-rspec-only-stub-a-method-when-a-particular-argument-is-passed
Flipper.should_receive(:enabled?).and_call_original
Flipper.should_receive(:enabled?).with(:premium_plus_features_beta).and_return(false)
When stubbing methods with specific arguments, you are only stubbing that specific method call with those specific parameters. All other calls to the method will fail with the error:
#<Foo (class)> received :bar with unexpected arguments
As the OP discovered, the solution here is to first stub ALL calls to the object with the and_call_through method, then stub the specific calls with the specific arguments you wish to stub.
From the OP's answer, the first line stubs ALL calls to the Flipper object and allows them to call through to the underlying code, and the second line stubs the call that receives :premium_plus_features_beta and returns false:
allow(Flipper).to receive(:enabled?).and_call_original
allow(Flipper).to receive(:enabled?).with(:beta).and_return(false)
Also, there's one other point to be made here. The code in the OP question used the OLD RSpec expectation syntax. The code in the OP answer uses the NEW RSpec stub syntax. So, when the code said this:
Flipper.should_receive(:enabled?).and_call_original
Flipper.should_receive(:enabled?).with(:beta).and_return(false)
What it was doing was this:
expect(Flipper).to have_received(:enabled?).and_call_original
expect(Flipper).to have_received(:enabled?).with(:beta).and_return(false)
Which is entirely different than what I think the OP was really trying to do:
before do
allow(Flipper).to receive(:enabled?).and_call_original
allow(Flipper).to receive(:enabled?).with(:beta).and_return(enabled?)
end
context "when the beta is disabled" do
let(:enabled?) { false }
it "hides the beta" do
...
end
end
context "when the beta is enabled" do
let(:enabled?) { true }
it "shows the beta" do
...
end
end
Finally, for those who are curious about why RSpec changed the syntax... The old syntax required a monkey patch on Object in order to add the should_receive method. I think the RSpec team preferred the new syntax because it no longer required the monkey patch.
The working answer is:
allow(Flipper).to receive(:enabled?).and_call_original
allow(Flipper).to receive(:enabled?).with(:premium_plus_features_beta).and_return(false)
a bunch of bad info on the internet lol

RSpec expectation on stub fails

Here's the call I would like to test expectations for:
UserMailer.invoice_paid(user, invoice).deliver_later
Rails 5 ActionMailer behaviour in :test mode seems to return nil on every method of an ApplicationMailer class. This should be fine since I can just stub it like so:
invoice_paid_dbl = double(ActionMailer::MessageDelivery)
allow(UserMailer).to receive(:invoice_paid).and_return(invoice_paid_dbl)
This expectation fails:
expect(UserMailer).to receive(:invoice_paid).once
While this one passes:
expect(invoice_paid_dbl).to receive(:deliver_later).once
Shouldn't that be impossible? I thought maybe the method chain was confusing RSpec, but splitting up the line into this has no effect:
mail = UserMailer.invoice_paid(user, invoice)
mail.deliver_later
Adding .with(any_args) to the stub and expectation also has no effect (since that's the default anyways). The failure is expected: 1 time with any arguments, received: 0 times with any arguments.
Not getting how you have stubbed methods, but think that following will work for you
You are trying to stub chain of methods so need to use stub_chain instead of stub
UserMailer.stub_chain(:invoice_paid, :deliver_later).and_return(:invoice_paid_dbl)
I hope this will work and solve you problem. For more details please check docs
I'll leave the question up in case it helps others, but this was actually the result of a silly mistake. I had expect(UserMailer).to receive(:invoice_paid) earlier in the it block, and it was passing. It was the second expectation of that type which was failing. Oops.

Method run on error with MiniTest

How can I have a method be called on error when using Minitest with Rails, to generate some extra information about the error that just happened?
Have you considered using something like pry or debugger to get more information? I also find liberally sprinkling puts statements throughout the code helpful to ensure that methods I think are being called, are actually called and to show variable values.
This was as simple as:
def teardown
if !passed?
call_method_for_failure
end
end

capybara error message, test still passes

When I run integrations tests with Capybara/webkit I get this error message:
undefined|36|TypeError: Result of expression 'node' [undefined] is not an object.
However it doesn't cause the test to fail and it doesn't always occur. When it does occur it seems to occur at the same point in the test (right before the final assertion)
test:
it "does something with things" do
#....
within('#dialog_box') do
click_button 'Save'
end
puts 'after within'
page.should have_content(thing_attrs[:name])
puts 'after assertion'
end
Final output:
after within
undefined|36|TypeError: Result of expression 'node' [undefined] is not an object.
after assertion
does something with things [pass]
How can I narrow down what is causing this? It makes test output ugly :)
I had a very similar problem, the error I was getting was:
undefined|0|TypeError: 'undefined' is not an object
In the end in order to figure out where it was coming from, I removed js files from application.js one by one until the error disappeared. Once I had narrowed it down, I figured out that there was, in fact, an undefined variable, which wasn't causing any issues and hence all tests were passing.
There might be a better way to do this, not really sure, but this approach worked for me. Best of luck.

Can rspec output the value that made a test fail?

I have statements like:
#obj[:attribute].eql?("TestValue").should be_true
And it would be nice if instead of just telling me that the test failed, it told me that it failed because #obj[:attribute] was nil or was 1234 or whatever it was. Is there any way to do this?
When doing something like
#obj.attribute.should eql(5)
and it throws an error, you'll usually see
expected 5
got 10
Is there a specific reason why you are doing eql??
Sure, rspec does output the difference between expected and actual values. You just need to change your matcher to provide more relevant information to you. Right now your expectation is that the expression #obj[:attribute].eql?("TestValue") will be true and rspec will inform you that it was false instead. If you rewrite your expectation as
#obj[:attribute].should eql("TestValue")
You should see the sort of output you are looking for.

Resources