I don’t tend to mock any services; I want my API test environment to match my intended live environment as closely as possible. This means using all the services used by live, I want to know of integration issues prior to going live.
Additionally, my tests write data, and they write data to the same system as live. If live writes to a MySQL database, so do all my tests, I have never seen the point of using a different engine for testing.
Most of my API tests are functional tests, they test a process. Unit tests are incredibly useful, but most of your tests should be functional or integration tests.
My goal with API testing is making sure everything works as expected for the user and more importantly, testing all the scenarios a user is likely to see, this means all the possible “400 errors”.
We need to test the happy path but we should focus most of our effort on the unhappy path, this is where the awkward bugs lie and the bugs we didn’t find during development. In addition to testing the happy path, I include tests to validate the structure of data. I’m a fan of self-documenting APIs and include response tests which validate that the generated OPTIONS response matches what I expect.
My action tests will include the expected, create, read, patch, and delete tests. They are not my priority, I create many more tests to ensure the correct validation messages are returned, ensuring parameters work as expected, testing where the user is likely to get stuck.
If there is a validation rule against a field, group of fields or some other explicit logic (PATCH body can’t be empty), I add a test to ensure it works as expected.
Up until recently, the API tests for the Costs to Expect API existed as a Postman collection. The collection worked until it didn’t. It is still a fantastic monitor but as the scope of the API grew, it became painstakingly difficult to ensure the code and tests were inline, authoring tests is also tedious and slow with Postman.
I have/am moving everything local and testing with PHPUnit, I couldn’t be happier, tests can be tied to releases, I can run them without cost and although I’m still functionally testing, I’m not limited to setting some fixed input and testing only the generated output.