Support the ongoing development of Laravel.io →
Article Hero Image

Lawman: Pest Architecture Testing for Saloon API Integrations

3 Jul, 2024 5 min read

Photo by Nikola Jovanovic on Unsplash

Introduction

If you've been reading my content for a while, you'll likely know that I love building and testing API integrations in Laravel. They're both really fun tasks that can be rewarding when you get them right.

Using Saloon for building API integrations in my Laravel projects has made this even more fun! It's a really powerful tool that makes it easy to build and test API integrations in Laravel. In fact, a huge amount of my book, Consuming APIs in Laravel, is dedicated to using Saloon to build and test API integrations.

Thanks to a cool package called "Lawman" by Jon Purvis, we can take the testing even further to add some really powerful Pest architecture tests to our Saloon integration code.

In this article, we're going to take a look at some examples of how you might want to use Lawman in your PHP and Laravel projects.

If you're not already familiar with what architecture testing is and what it achieves, you might want to check out my "Architecture Testing in Laravel with Pest" article which explains it in more detail.

Installation

To get started with Lawman, you'll first need to install it. You can do this using Composer by running the following command in your project root:

composer require jonpurvis/lawman --dev

It's worth noting that we're using the --dev flag here to ensure that Lawman is only installed in your development environment. This is because Lawman is a testing tool and you don't want it to be included in your production environment.

Usage Examples

Now that you've got Lawman installed, you can start using it to test your Saloon integrations.

To get a good idea of the architecture testing expectations it provides, let's take a look at some examples.

We'll imagine we've built a simple GitHub API integration in a Laravel application using Saloon. We might have the following files that contain our integration code:

Connector:

  • app/Http/Integrations/GitHub/GitHubConnector.php

Requests:

  • app/Http/Integrations/GitHub/Requests/CreateRepoRequest.php
  • app/Http/Integrations/GitHub/Requests/GetReposRequest.php

Let's look at a test that we could write for our app/Http/Integrations/GitHub/GitHubConnector.php file using Lawman's expectations:

use App\Http\Integrations\GitHub\GitHubConnector;

test('connectors')
    ->expect(GitHubConnector::class)
    ->toBeSaloonConnector()
    ->toUseAcceptsJsonTrait()
    ->toUseAlwaysThrowOnErrorsTrait()
    ->toBeTriedAgainOnFailure()
    ->toHaveRetryInterval()
    ->toUseExponentialBackoff()
    ->toHaveRateLimits();

In the architecture test above, we're asserting that our App\Http\Integrations\GitHub\GitHubConnector meets several criteria:

  • It extends the Saloon\Http\Connector class.
  • It uses the Saloon\Traits\Plugins\AcceptsJson trait.
  • It uses the Saloon\Traits\Plugins\AlwaysThrowOnErrors trait.
  • It has a tries property that is greater than 1 (for retrying requests on failure).
  • It has a retryInterval property (used for specifying how long to wait between retries).
  • It has a useExponentialBackoff property (used for specifying whether to use exponential backoff for the request retries).
  • It uses the Saloon\RateLimitPlugin\Traits\HasRateLimits plugin.

If any of the above criteria aren't met, the test will fail.

You may also want to write a test to ensure that all the PHP files within the App\Http\Integrations\GitHub\Requests directory are Saloon request classes:

test('requests')
    ->expect('App\Http\Integrations\GitHub\Requests')
    ->toBeSaloonRequest();

The cool thing about Lawman is that you're not restricted to only using Lawman's expectations - you can still use Pest's default expectations too. For example, we could use some of Pest's default expectations to the update the test above:

test('requests')
    ->expect('App\Http\Integrations\GitHub\Requests')
    ->toBeSaloonRequest()
    ->toHaveSuffix('Request')
    ->toUseStrictTypes()
    ->toBeFinal();

In the test above, we're asserting that all the PHP files within the App\Http\Integrations\GitHub\Requests namespace meet the following criteria:

  • Must be a Saloon request class
  • The classname must end with "Request"
  • The files are using strict types
  • The files are marked as final

Lawman also allows you to ensure that given files in a namespace are using the correct HTTP methods. For example, you may want to assert that a request class sends a GET request and also has caching enabled:

use App\Http\Integrations\GitHub\Requests\GetReposRequest;

test('get requests')
    ->expect(GetReposRequest::class)
    ->toSendGetRequest()
    ->toHaveCaching();

Another example might be to assert that a request class sends a POST request and has a JSON body:

use App\Http\Integrations\GitHub\Requests\CreateRepoRequest;

test('post requests')
    ->expect(CreateRepoRequest::class)
    ->toSendPostRequest()
    ->toHaveJsonBody();

Available Expectations

We can't cover all the expectations that Lawman provides (this article would end up being huge!). But here's a list of the other expectations that are available to you:

Authentication

  • toUseTokenAuthentication
  • toUseBasicAuthentication
  • toUseCertificateAuthentication
  • toUseHeaderAuthentication

Caching

  • toHaveCaching

Connector

  • toBeSaloonConnector

Pagination

  • toUsePagedPagination
  • toUseOffsetPagination
  • toUseCursorPagination
  • toUseCustomPagination

Properties

  • toSetConnectTimeout
  • toSetRequestTimeout
  • toBeTriedAgainOnFailure
  • toHaveRetryInterval
  • toUseExponentialBackoff
  • toThrowOnMaxTries

Rate Limiting

  • toHaveRateLimits

Requests

  • toBeSaloonRequest
  • toHaveRequestMethod
  • toSendGetRequest
  • toSendPostRequest
  • toSendHeadRequest
  • toSendPutRequest
  • toSendPatchRequest
  • toSendDeleteRequest
  • toSendOptionsRequest
  • toSendConnectRequest
  • toSendTraceRequest
  • toHaveJsonBody
  • toHaveMultipartBody
  • toHaveXmlBody
  • toHaveFormBody
  • toHaveStringBody
  • toHaveStreamBody

Response

  • toBeSaloonResponse

Traits

  • toUseAcceptsJsonTrait
  • toUseAlwaysThrowOnErrorsTrait
  • toUseTimeoutTrait
  • toUseAuthorisationCodeGrantTrait
  • toUseClientCredentialsGrantTrait

Conclusion

Hopefully, this article has given you an insight into how to use Lawman to add some powerful Pest architecture tests to your Saloon integration code.

If you enjoyed reading this post, you might be interested in checking out my 440+ page ebook "Consuming APIs in Laravel" which teaches you how to use Laravel to consume APIs from other services.

If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter below.

Keep on building awesome stuff! 🚀

Last updated 3 weeks ago.

driesvints, teephe liked this article

2
Like this article? Let the author know and give them a clap!
ash-jc-allen (Ash Allen) I'm a freelance Laravel web developer from Preston, UK. I maintain the Ash Allen Design blog and get to work on loads of cool and exciting projects 🚀

Other articles you might like

Article Hero Image November 18th 2024

Laravel Custom Query Builders Over Scopes

Hello 👋 Alright, let's talk about Query Scopes. They're awesome, they make queries much easier to r...

Read article
Article Hero Image November 19th 2024

Access Laravel before and after running Pest tests

How to access the Laravel ecosystem by simulating the beforeAll and afterAll methods in a Pest test....

Read article
Article Hero Image November 11th 2024

🍣 Sushi — Your Eloquent model driver for other data sources

In Laravel projects, we usually store data in databases, create tables, and run migrations. But not...

Read article

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2024 Laravel.io - All rights reserved.