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.
Related
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
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
I tried testing this method in rspec:
def resend_if_failed
ResendWorker.new(self).resend_message
end
How do I test that ResendWorker.new(self).resend_message gets executed?
If you have the instance in your spec, you can just do :
expect(instance).to receive(:resend_if_failed)
instance.resend_if_failed
Obviously I guess resend_if_failed is triggered by another method.
Then if necessary, test resend_if_failed behaviour in isolation.
worker = double
allow(ResendWorker).to receive(:new).and_return(worker)
expect(worker).to receive(:resend_message)
instance.resend_if_failed
I have a static method that is doing HTTP POST to a remote server.
I want to test that this method is called with the correct arguments whenever its needed, but I also want to prevent it from actually running so it won't execute the actual HTTP request while testing.
how can I stub that method globally so I won't have to do it in every test case for preventing it from actually running ?
and if doing so, how do I unstub it for the specific test case of testing the actual method ?
If you simply want to stub the method in all your specs and check that it receives the correct arguments whenever it is called (assuming they are the same in each case), you can just add a stub to your spec_helper in a before(:each) block:
RSpec.configure do |config|
...
config.before(:each) do
SomeClass.stub(:some_static_method).with(...).and_return(...)
end
...
end
That will fail if the stub is called with anything but the arguments you specified. Note that you can also use should_receive as #appneadiving suggested, but you'll have to call it with any_number_of_times to make sure it doesn't fail if you don't call it, and that's basically the same as using a stub (see this discussion).
Another route is to use the webmock gem to stub requests to a given URL. Using this approach you don't (necessarily) need to stub your method, you can just let it run as usual with the certainty that whenever it tries to access the server with the arguments you specify, it will get a given response.
To use the webmock throughout your specs you'll have to add a line in spec_helper like the one above, calling the stub_request method, e.g.:
stub_request(:any, "www.example.com").with(:query => { :a => "b"}).to_return(...)
Hope that helps.
In my current Rails 3 app, I'm doing some unit testing to make sure that calls to update S3 are only done under certain situations. I don't want to update S3 during tests, so I'm using Mocha to stub out the behaviour. Is there a way to make sure a function is called using mocha? I've taken a look at Expectations, and unless I'm doing it wrong, it seems I have to do:
object.expects(:function_name).once
However, this does not yield the desired results: This will flag an error if function_name is called twice(which is desired), it will NOT flag an error if it is only called once(as it should), but the problem is it WILL NOT flag an error if the function is called zero times. I need a way to make sure it is called. It seems like mocha should support this, so maybe I'm doing it wrong. Any help would be greatly appreciated.
***** CORRECTION:
Turns out that I was doing it right, except that the mocha_verify method wasn't being called automatically. For anyone who is having a similar problem, check out Ole Morten Amundsen's answer over here: Mocha Mock Carries To Another Test
or just
object.expects(:function_name).twice
alternatively, if it has differnet input you should test that
resultmock = mock
object.expects(:function_name).with(someobject).returns(mock)
resultmock.expects(:something).returns(true)
object.expects(:function_name).with(resultmock)
don't know if this helps, but it should give you a kick start. FYI: 'once' is default. Good luck, do TDD (=test-first) or mocking will be a pain :)
Be sure to load mocha last, so it is really being loaded, as in my answer here:
Mocha Mock Carries To Another Test
Try:
object.expects(:function_name).at_least_once
Have a look at the docs: http://mocha.rubyforge.org/classes/Mocha/Expectation.html#M000042