Most APIs have like a testing environment where you can post to. Not sure about the services you said but you can look for that
Testing an API call to another external service (Stripe, Instagram, et. al)
I've been looking around about this but I'm still unsure of a "good" way to go about doing this.
How do people go about testing calls to external APIs such as Stripe, Instagram, et. al? It's not exactly convenient to make an actual call to a testing API via Stripe every time I run my functional tests or whatnot.
For functional/acceptance testing you I would use 3rd party API testing evironment, in some integration testing I would mock with for example mockery or AspectMock, depending how good my code is tested in how much code coverage I have :)
How about executing the remote API call once and caching the response?
Jeffrey covered a solution in https://laracasts.com/lessons/testing-http-requests with PHP-VCR
I have done this with Stripe and a few other services. Let's take Stripe as an example.
For many things, you don't want to hit Stripe. For example, I have a Stripe webhook handler with many tests for all the webhooks I might receive. Doing this with real Stripe interactions would be very slow.
Instead, I made some Stripe transactions, and then went to my Stripe dashboard and copied the webhook data. I save these as sample webhooks (e.g. charge.refunded.json) and use them to test my application. It's important to have realistic data.
I consider these to be unit tests, even though they are hitting the file system. In any case, they run extremely fast.
In other cases, you might want to make real calls to Stripe. For example, I have a StripeApi class as a wrapper for my Stripe interactions. It's an important component of my system, so I test it. Yes, these involve calls to the Stripe API, so they are slow tests.
But you don't need to run all your tests all the time. I have an "external" test suite where I put all these tests that interact with external APIs (apart from acceptance tests, which have their own suite). They don't interfere with the speed of other tests.
When you're making real calls to Stripe, I found it's better not to rely on existing test data. Each test should create any objects it requires, so that you can clear out Stripe's test data at any time. For example, I have an acceptance test that cancels a subscription. Instead of relying on an existing subscription (and thereby coupling my test to the current state of Stripe's test data), I create the subscription in the test before cancelling it.
In other words, all tests should handle their own setup. This allows me to reset Stripe's test data every time I reset my staging site, which is necessary to avoid bizarre bugs where "old" Stripe webhooks are applied to the "fresh" database.
@MikeHopley , your setup sounds really good and I'd like to have something similar.
Did you use Cashier in your StripeAPI class? I'm just now implementing billing, and have added the Billable trait to my User model, but it makes the User model and Stripe interactions tightly coupled and I don't see how I can extract the Stripe interactions. I might be able to add the Billable trait to the StripeAPI class instead, not sure how that would work.
@dezgo I did not use Cashier, for two reasons:
- Cashier did not exist when I started
- Cashier is (or at least was) tightly coupled to Stripe
Cashier can now accept Braintree. However, I just took a quick look at the BillableTrait code, and it still looks coupled to Stripe. So I'm not really sure how it works.
From looking at the code, I am doubtful that you could use Cashier together with the setup that I have. They are probably incompatible approaches.
The main benefit of using Cashier is that you don't have to write this code yourself! If I were starting from scratch, I would most likely just use Cashier and no longer need my own StripeAPI class or webhook handling code. Or maybe I would even just use Spark!
Please or to participate in this conversation.