I'm trying to test my rails application which using Stripe APIs, So I started with models, I'm using Rspec, The model which i want to test is called bank_account.rb inside it there is a function called (create_bank_account) with argument (bank_token) its pseudocode is something like this:
def create_bank_account(bank_token)
# make a Stripe request and save it in local variable
# save needed data in my bank_account table in my DB
end
when i started to test this function, I found that there is an API call inside it, Which is not good, I need my test not to depend on Internet, So after searching I found 'StripeMock` gem, It is useful and i started to use it with Rspec, but I found my self writing a test like this:
it 'with valid bank_token` do
# create a double for bank_account
# using StripeMock to get a faked response for creating
# new bank_account
# expect the doube to receive create_bank_account
# function and response with saving the data inside the DB
end
but after writing this I noticed that I didn't actually run create_bank_account function i faked it, So my questions are:
1- How can i test function that includes API request but run the function it self not faking it?
2- I read a lot about when we use doubles and stubs and what i understood is when a function is not completed, but if the functions is already implemented should i use doubles to avoid something like functions that call APIs?
First and foremost:
bank_account.bank_account.create_bank_account.If you do either of these things, in a test that is supposed to be testing behaviour of
BankAccount#create_bank_account, then your test is worthless.(To prove this point, try writing broken code in the method. Your tests should obviously fail. But if you're mocking the method, everything will remain passing!!)
One way or another, you should only be mocking the
striperequest, i.e. the behaviour at the boundary between your application and the internet.I cannot provide a working code sample without a little more information, but broadly speaking you could refactor your code from this:
To this:
...And then in your test, you can use
StripeMockto only fake the response ofBankAccount#make_stripe_request.If the code is not so easy to refactor(?!), then stubbing the
Stripelibrary directly like this might not be practical. An alternative approach you can always take is use a library likewebmockto simply intercept all HTTP calls.