Stubbing stripe subscription error - ruby-on-rails

I'm trying to test my payment process and I'm stuck with the problem of stubbing the subscription, this is the error message I get :
Double "Stripe::Customer" received unexpected message :[] with ("subscription")
This is the relevant part of the code for stubbing subscription :
#subscription = double('Stripe::Subscription')
#subscription.stub(:id) { 1234 }
#customer.stub(:subscription) { [#subscription] }
When I try the payment with the test card and it works, but I want to have an automated test in place in case something changes which could impact the payments
Edit :
per mcfinnigan suggestion I changed he last bit of code to :
#customer.stub(:[]).with(:subscription).and_return { [#subscription] }
And now I get this error :
Double "Stripe::Customer" received :[] with unexpected arguments
expected: (:subscription)
got: ("subscription")
Please stub a default value first if message might be received with other args as well.

You're not stubbing the right thing - your error indicates that something is attempting to call the method [] (i.e. array or hash dereferencing) on your double #customer.
Check your code and see whether you are sending a [] to a customer object anywhere.
Are you positive the last line should not be
#customer.stub(:[]).with(:subscription).and_return { [#subscription] }
instead?

Related

OPA unit-test failing, How to output response variable?

Newbie to OPA, I am writing OPA unit test case.
test_valid_type {
response = evaluate with
input as valid_type
response == "approved"
}
it's failing response == "approved". I want to see the output of response variable, how do i output it?
Try the trace method provided by OPA for debugging.
https://www.openpolicyagent.org/docs/latest/policy-reference/#debugging
This will let you print the output.
In your example you can add trace(response) which will print the response output.
After reading many documention finally found it.
trace(variable)
prints the content of the variable.
[Ref][1]

Trouble mocking `Resolv::DNS.open`

I'm trying to mock the code below using MiniTest/Mocks. But I keep getting this error when running my test.
Minitest::Assertion: unexpected invocation: #<Mock:0x7fa76b53d5d0>.size()
unsatisfied expectations:
- expected exactly once, not yet invoked: #<Mock:0x7fa76b53d5d0>.getresources("_F5DC2A7B3840CF8DD20E021B6C4E5FE0.corwin.co", Resolv::DNS::Resource::IN::CNAME)
satisfied expectations:
- expected exactly once, invoked once: Resolv::DNS.open(any_parameters)
code being tested
txt = Resolv::DNS.open do |dns|
records = dns.getresources(options[:cname_origin], Resolv::DNS::Resource::IN::CNAME)
end
binding.pry
return (txt.size > 0) ? (options[:cname_destination].downcase == txt.last.name.to_s.downcase) : false
my test
::Resolv::DNS.expects(:open).returns(dns = mock)
dns.expects(:getresources)
.with(subject.cname_origin(true), Resolv::DNS::Resource::IN::CNAME)
.returns([Resolv::DNS::Resource::IN::CNAME.new(subject.cname_destination)])
.once
Right now you are testing that Resolv::DNS receives open returns your mock but
since you seem to be trying to test that the dns mock is receiving messages you need to stub the method and provide it with the object to be yielded
Try this instead:
dns = mock
dns.expects(:getresources)
.with(subject.cname_origin(true), Resolv::DNS::Resource::IN::CNAME)
.once
::Resolv::DNS.stub :open, [Resolv::DNS::Resource::IN::CNAME.new(subject.cname_destination)], dns do
# whatever code actually calls the "code being tested"
end
dns.verify
The second argument to stub is the stubbed return value and third argument to stub is what will be yielded to the block in place of the original yielded.
In RSpec the syntax is a bit simpler (and more semantic) such that:
dns = double
allow(::Resolv::DNS).to receive(:open).and_yield(dns)
expect(:dns).to receive(:getresources).once
.with(subject.cname_origin(true), Resolv::DNS::Resource::IN::CNAME)
.and_return([Resolv::DNS::Resource::IN::CNAME.new(subject.cname_destination)])
# whatever code actually calls the "code being tested"
You can write more readable integration tests with DnsMock instead of stubbing/mocking parts of your code: https://github.com/mocktools/ruby-dns-mock

Avoid recreating the subject in RSpec

Say I have the following test
describe "bob" do
subject {
response = get "/expensive_lookup"
JSON.parse(response.body)
}
its(["transaction_id"]) { should == 1 }
its(["order_id"]) { should == 33 }
end
Then for each its() {} the subject will be reevaluated, which in my case it is a very slow lookup.
I could bundle all my tests together in one like
describe "bob" do
subject(res) {
response = get "/expensive_lookup"
JSON.parse(response.body)
}
it "returns the right stuff" do
res["transaction_id"]).should == 1
res["order_id"].should == 33
end
end
But this makes it less obvious which line of the test has failed if there is a failure.
Is there a way I can stop the subject from being reevaluated for each it block?
You can put that in to a before(:all) block. I don't know if that syntax has changed in a new rspec version, but regardless, your test would become this:
before(:all) do
response = get "/expensive_lookup"
#res = JSON.parse(response.body)
end
it "returns the right transaction ID" do
#res["transaction_id"].should == 1
end
# etc
The pro is that the code in the before-all block gets run just once for your spec. The con is that, as you can see, you can't take advantage of the subject; you need to write each more explicitly. Another gotcha is that any data saved to the test database is not part of the transaction and will not be rolled back.
There are two possible source of issues
Network request is slow/prone to fail
You should really mock all you network requests, slow or not.
The gem VCR is excellent. It makes it trivial to run your request once and persist the result for subsequent testing.
Building the immutable subject is slow
If you have multiple it blocks, the subject will be rebuild every time. Assuming you don't modify the subject, you can build it once.
You can use before(:all):
before(:all) { #cache = very_long_computation.freeze }
subject { #cache }
Note: that I call freeze to avoid modifying it by mistake, but of course that's not a deep freeze so you still need to mind what you are doing. If you are mutating your subject, your tests are no longer independent and shouldn't share the subject.

error message test on minitest

I use mini_test for testing. I have a code part like below.
raise Type_Error, 'First Name must not be empty' if #person.first_name == nil
How can I write this code's test?
Thanks...
I think you want assert_raises, which asserts that the block/expression passed to it will raise an exception when run.
For example, one of my projects has the following minitest:
test 'attempting to create a CreditCard that fails to save to the payment processorshould prevent the record from being saved' do
assert_equal false, #cc.errors.any?
failure = "simulated payment processor failure"
failure.stubs(:success?).returns(false)
failure.stubs(:credit_card).returns(nil)
PaymentProcessor::CreditCard.stubs(:create).returns(failure)
assert_raises(ActiveRecord::RecordNotSaved) { create(:credit_card) }
end
What this does, in my case, is:
Create a simulated failure message from the payment processor API
Stub the creation of a credit card on the payment processor to return the simulated failure
Try to create a credit card, simulating that the payment processor has returned a failed status, and assert that my internal save/create method throws an error under these conditions
I should say that this test code includes things in addition to minitest, such as FactoryGirl, and (I think) shoulda and mocha matchers. In other words, what is shown above isn't strictly minitest code.
raise Type_Error, 'First Name must not be empty' if #person.first_name == nil
For testing above line, I wrote a test like below. I used minitest::spec for this.
def test_first_name_wont_be_nil
person.name = nil
exception = proc{ Context.new(person).call }.must_raise(TypeError)
exception.message.must_equal 'First Name must not be empty'
end
Context is place where make some process.

Customizing jUnit AssertFailure Error messages - combined with slf4j logging

I am new to jUnit and Selenium. Currently, we are doing a POC in our project for evaluating the tools' suitability.
One of the key requirements for us would be use friendly messages in case of assertion failures and verify Failures. The objective is to have those analyzed by manual testers by keeping those user intuitive.
I am trying out SLF4J for logging INFO messages for user friendly messages.
The challenge I am facing is that - when assertions fail, how to pass a custom message instead of jUnit default message?
For example, I want to get rid of the following default assertion failure message
expected "Health A-Z" to match glob "Health A-ZZ" (had transformed the glob into regexp "Health A-ZZ"
and frame it as
The title of the Menu Item doesn't match the expected value "Health A-ZZ". The actual value seen is "Health A-Z"
Question1 - Is there a way I override the default message with what I want?
Question2 - Can I pass variable parameters to the message and make it a dynamic message?
Sample Code:
try {
assertEquals("Health A-ZZ", selenium.getText("//div[#id='topnav']/ul/li[2]/a"));
logger.info("SUCCESS: Menu Item {} title verification Passed. EXPECTED : A-Z and Actual: {}",mainCounter, selenium.getText("//div[#id='topnav']/ul/li[2]/a"));
}
catch (AssertionError e) {
logger.error("FAILURE: Menu Item {} title verification Failed. EXPECTED : A-ZZ and Actual: {}",mainCounter, selenium.getText("//div[#id='topnav']/ul/li[2]/a"));
}
I get the assertFailure message printed out twice.. One with the error message in the catch block above and the other, the default junit assertfailre message like the one I mentioned above I wanted to get rid of.
Thanks in Advance.
Regards,
Prakash
You can use the Junit assert function.
assertEquals(message, expected, actual)
This will print the message that has been given in the message String in case of failure.
You can also pass String variable to the "message".

Resources