Testing And Debugging Laravel APIs

https://images.unsplash.com/photo-1617042375876-a13e36732a04?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=Mnw4NjkxNHwwfDF8c2VhcmNofDIxfHxjb2RlfGVufDB8MHx8fDE2MzQ5MjUwODQ&ixlib=rb-1.2.1&q=80&w=1080

Hey guys, last year I published Laravel API Test Helper, a Laravel package that can help you in developing and debugging your Laravel APIs. Since last year, 80% of my work has been around building APIs both at Across The Horizon Technologies and at Greenlite Nigeria. That’s why I have been putting out packages, which are code snippets that I end up duplicating across different projects.

In this tutorial, I will walk you through what the package is all about and how it can help speed up your API development with the Laravel framework.

Laravel Api Test Helper is a trait based Laravel package, meaning that it just contains a PHP trait that you can include in your test class, that’s all.

Let me show you 🙂

Installation & Setup

For this tutorial, I believe you have created a Laravel application . If you are new to Laravel, you can check out my Laravel Series for beginners.

First, let’s install the package with via composer:

composer require stephenjude/api-test-helper --dev

Next, we need you to include the helper trait inside our TestCase.php. This class comes with every Laravel installation. You can find it inside the test directory of your project.

<?php
namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Stephenjude\ApiTestHelper\WithApiHelper;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
    use WithApiHelper; 
  
    ...
}

You can choose to include this trait to the particular test class that contains your API tests, but keeping it here makes it accessible to all our test class since they will extend the TestCase abstract class.

Usage: Testing and Debugging APIs

For this tutorial, we will create a single endpoint that fetches all the users in our database. Let start by creating a test class for our user list endpoint.

php artisan make:test UserApiTest

This will create a test file inside the tests\Feature directory in your Laravel project. This is the default for Laravel, but you can configure this directory to suit your project 🙂

PS: Make sure you have added your database credentials to your .env file.

Now let’s add the tests for our user list endpoint. We will use the Laravel getJson() to make a request to our endpoint and then set it to our test helper property $this->response. This gives the Api Test Helper package access to the api response, with which the helper trait can help you test and debug the response.

<?php

namespace Tests\Feature;

use App\Models\User;
use Tests\TestCase;

class UserApiTest extends TestCase
{
    public function test_get_user_list()
    {
        User::factory()->create();

        $this->response = $this->getJson('api/users');

        $this->dumpApiData(); 
    }
}

Dumping API Response: dumpApiData()

So I started out with the dumpApiData() with allows us to dump the response returned from our response, this response can either be a valid response or an error response from the api or your application error itself.

Log API Response: logApiData()

You can also log the response of your api by calling the logApiData() . This method logs all the response on your app to your log file.

...
$this->response = $this->getJson('api/users');

$this->logApiData();
...

Decoding API Response: decodeApiResponse()

You can also decode the API response by calling the decodeApiResponse() method which returns the response from your API.

PS: I will advice the use of the json() method provided in Laravel. I have already built this package before I learned about it. $this->response->json()

Testing Successful API Response

To test successful response, this package provides three(3) methods which I am going to explain with example.

To make a valid request, lets create a valid controller and route that can handle our request.

php artisan make:controller UserApiController -r

Here is our controller class with a valid response that returns list user.

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;

class UserApiController extends Controller
{
    public function index()
    {
        return response()->json([
            'success' => true,
            'data' => User::all(['id', 'name', 'email',])
        ]);
    }
    
    ...

Now let’s add our user list route to api.php

Route::get('/users', [UserApiController::class, 'index']);

Now that we have a valid response for our endpoints, lets test the valid response methods.

assertApiSuccess()

...
$this->response = $this->getJson('api/users');

$this->assertApiSuccess(); 
...

The method asserts the response contains the success field with true value 'success' => true or fails if it doesn’t.

assertApiResponse($data)

The method asserts the response contains the actual data or fails if it doesn’t.

...
$user = User::factory()->create()->only(['id', 'name', 'email']);

$this->response = $this->getJson('api/users/'.$user['id']);

$this->assertApiResponse($user); 
...

assertApiResponseCollection($data)

The method asserts the response contains the actual collection or fails if it doesn’t.

...
User::factory()->count(2)->create();

$this->response = $this->getJson('api/users');

$this->assertApiResponseCollection(User::all(['id', 'name', 'email'])); 
...

Conclusion

I believe you have learnt how to speed up your development process with this package and if you are new, you basically understand how to test your endpoints. You can find the link to the repository for this tutorial below and please don’t forget to star the package repository.

Laravel News Links

Deploying Laravel API on AWS Lambda

https://production.ams3.digitaloceanspaces.com/2021/08/Social-Sharing-photo-Template-1-13.png

AWS Lambda brought the term “serverless” into reality and shook the world of software development.

It gained a lot of popularity in the last few years and is one of the fastest-growing technologies provided by Amazon. One of its strengths is the ability to pay only for the amount of time it takes to run the code and pay nothing while the code isn’t running.

To accomplish this business model, AWS made Lambda scalable by default. You only provide the amount of memory your process needs and the cloud provider will be responsible for provisioning as much hardware as necessary every time your source code needs to be executed.

I have been working with AWS for 4 years and AWS Lambda in particular for 2 years. In this post, I want to share hands-on experience on deploying a Laravel API service on AWS Lambda.

Requirements

To follow along, you’ll need a few ingredients:

– AWS Account

– IAM Access Key / Secret Key

– PHP

– [Composer](https://getcomposer.org/download/)

– [NPM](https://nodejs.org/en/download/)

– [Serverless](https://goserverless.com)

– [Bref](https://bref.sh)

– [Laravel](https://laravel.com)

– [Optional] Docker

If you have an AWS Account already, everything else is manageable.

Let’s get started!

IAM Access

Let’s first start by generating programmatic access to AWS. We’ll need it so that we can provide the Serverless Framework with the ability to provision/deploy AWS lambda into our AWS account.

Log into your AWS account and go to IAM → Users → Add User. Choose a username for your account, check the Programmatic Access checkbox, and hit Next: Permission.

Under Attach existing policies directly, select the AdministratorAccess policy. We can now proceed to Next: Tags and subsequently Next: Review (Tags are optional).

Take this opportunity to double-check the configuration. Once you click Create User, AWS will show you the Access Key and Secret Key. The Secret Key is unrecoverable, so make sure to save it.

PHP, Composer, NPM, and Severless

If you have these tools installed in your environment, you may skip this step. Otherwise, I’ll show you how I install these tools inside a docker container.

#!/usr/bin/env sh

docker run --rm -v $(pwd):/app -w /app -it alpine:3.14 sh

apk add php8 php8-phar php8-curl php8-openssl php8-dom php8-xml php8-xmlwriter php8-xmlreader php8-tokenizer php8-mbstring php8-fileinfo php8-simplexml

apk add composer npm

cp /usr/bin/php8 /usr/bin/php

npm install -g serverless

This sequence of commands will start an Alpine Linux container and install PHP 8, Composer, NPM, and Serverless. Keep this container open because we’ll continue using it for the next steps.

Laravel and Bref

Let’s start a new Laravel project and install Bref using Composer.

#!/usr/bin/env sh

composer create-project laravel/laravel my-api
cd my-api
composer require bref/bref
./vendor/bin/bref init
0
rm index.php

The 0 above is to automatically select the option [0] Web application. Bref will then create serverless.yml and index.php. Since we’re using Laravel, we can remove the index.php and just keep the serverless.yml.

Before we move on to Serverless, let’s add a sample routing for our API by editing the routes/api.php file.

<?php

Route::get('/hello', fn () => response(['data' => 'Hello from Laravel!']));

Remember that by default the api.php folder is configured with the /api prefix, so our route will actually be /api/hello.

Serverless

Before we dive into the serverless.yml template, let’s configure the Serverless Framework. We can do that in two ways:

export AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY_HERE
export AWS_SECRET_ACCESS_KEY=YUR_SECRET_KEY_HERE

The framework will automatically pick up the credentials from the environment variable and perform deployments into your account.

The 2nd approach is to use serverless config credentials:

serverless config credentials --provider aws --key YOUR_ACCESS_KEY_HERE --secret YOUR_SECRET_KEY_HERE

After configuring the credentials for your AWS account, let’s tweak the serverless.yml template generated by Bref:

service: app

provider:
  name: aws
  region: us-east-1
  runtime: provided.al2

plugins:
  - ./vendor/bref/bref

functions:
  api:
    handler: public/index.php
    environment:
        LOG_CHANNEL: stderr
        SESSION_DRIVER: array
        CACHE_DRIVER: array
    description: ''
    timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
    layers:
      - ${bref:layer.php-80-fpm}
    events:
      - httpApi: '*'

# Exclude files from deployment
package:
  patterns:
    - '!node_modules/**'
    - '!tests/**'

We change the handler from index.php to public/index.php as that’s the entry point for a Laravel application. There are also 3 important environment variables: LOG_CHANNEL, SESSION_DRIVER, and CACHE_DRIVER. The stderr driver will automatically drive log messages into CloudWatch and the array driver will essentially disable Session and Cache.

Deployment

To deploy the project, let’s issue the following command:

sls deploy

The output should look like this:

/app/my-api # sls deploy
Serverless: Deprecation warning: Detected ".env" files. In the next major release variables from ".env" files will be automatically loaded into the serverless build process. Set "useDotenv: true" to adopt that behavior now.
            More Info: https://www.serverless.com/framework/docs/deprecations/#LOAD_VARIABLES_FROM_ENV_FILES
Serverless: Deprecation warning: Resolution of lambda version hashes was improved with better algorithm, which will be used in next major release.
            Switch to it now by setting "provider.lambdaHashingVersion" to "20201221"
            More Info: https://www.serverless.com/framework/docs/deprecations/#LAMBDA_HASHING_VERSION_V2
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Service files not changed. Skipping deployment...
Service Information
service: app
stage: dev
region: us-east-1
stack: app-dev
resources: 11
api keys:
  None
endpoints:
  ANY - https://0000000000.execute-api.us-east-1.amazonaws.com
functions:
  api: app-dev-api
layers:
  None

You can use your endpoint to test the API. It should look like this: 

https://your_api_gateway_id.execute-api.us-east-1.amazonaws.com/api/hello

This is pretty much it! Your source code is now available behind API Gateway and Lambda and you’ll only pay for the time it takes for your code to execute.

Enforcing JSON Response

If we try to load an invalid route, say https://your_api_gateway_id.execute-api.us-east-1.amazonaws.com/whatever, we’ll get a fatal error because Laravel will try to write the compiled php files for Blade. We can fix that by adjusting the VIEW_COMPILED_PATH environment variable. But since the focus is to deploy API-based projects, we can also add a nice little middleware to enforce that every HTTP Response will be JSON.

<?php

namespace App\Http\Middleware;

use Closure;

class EnforceJsonResponse
{
    public function handle($request, Closure $next)
    {
        $request->headers->set('Accept', 'application/json');

        return $next($request);
    }
}

Then we can register it inside Kernel.php.

Conclusion

This introduction to Serverless with Laravel gives an overview of the foundation behind treating AWS Lambda as a hosting provider that only charges for execution time.

Although it is important to consider the aspect of running code on a read-only environment (with limited disk space under /tmp) and how two requests may not share the same live “container”, this approach doesn’t have a strong impact on the development practices and day-to-day operation of developers.

Providing APIs behind AWS Lambda makes them highly scalable and cheap if you have little to no usage at night or weekends, for instance.

Laravel News Links

Laravel Cashier Provider

https://avatars.githubusercontent.com/u/92824325?s=280&v=4

Pinned


  1. Cashier provides an expressive, fluent interface to manage billing services.



    PHP



    4

  2. Cashier Provider Driver Template



    PHP

  3. Cashier Provider Authorization Driver Template



    PHP



    1

  4. Driver for payment with QR codes via Sber (see cashier-provider/core)



    PHP



    2

  5. Driver for payment with QR codes via Tinkoff (see cashier-provider/core)



    PHP



    1

  6. Driver for managing cash payments in the Cashier Provider ecosystem



    PHP



    2


Repositories


  • tinkoff-qr


    Public

    Driver for payment with QR codes via Tinkoff (see cashier-provider/core)



    PHP



    1


    MIT


    0



    0



    0


    Updated Oct 24, 2021


  • sber-auth


    Public

    Sber API Authorization Driver



    PHP



    1


    MIT


    0



    0



    0


    Updated Oct 24, 2021


  • sber-qr


    Public

    Driver for payment with QR codes via Sber (see cashier-provider/core)



    PHP



    2


    MIT


    0



    0



    0


    Updated Oct 24, 2021


  • core


    Public

    Cashier provides an expressive, fluent interface to manage billing services.



    PHP



    4


    MIT


    0



    0



    0


    Updated Oct 24, 2021


  • cash


    Public

    Driver for managing cash payments in the Cashier Provider ecosystem



    PHP



    2


    MIT


    0



    0



    0


    Updated Oct 24, 2021


  • driver


    Public template

    Cashier Provider Driver Template



    PHP


    0


    MIT


    0



    0



    0


    Updated Oct 24, 2021


  • driver-auth


    Public template

    Cashier Provider Authorization Driver Template



    PHP



    1


    MIT


    0



    0



    0


    Updated Oct 24, 2021



  • PHP



    1


    MIT


    0



    0



    0


    Updated Oct 24, 2021

Most used topics

Loading…

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.

Laravel News Links

Short URL v6.0.0 released

https://opengraph.githubassets.com/d5515559507e3719b5e34e334c25d68142fec164e7e542a28166483fd39bd919/ash-jc-allen/short-url/releases/tag/v6.0.0

Added

  • Added the ability to forward query parameters to the destination URL. Huge thanks to @julienarcin for this contribution! (#94)

Changed

  • Dropped support for Laravel 6 and 7 (#96, #98)
  • Dropped support for PHP 7.3 and 7.4 (#85)

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session.
You signed out in another tab or window. Reload to refresh your session.

Laravel News Links

Comic for October 24, 2021

https://assets.amuniversal.com/b557a1e0fa1b0139793a005056a9545d

Thank you for voting.

Hmm. Something went wrong. We will take a look as soon as we can.

Dilbert Daily Strip

Damn, this is great advice.

Via LawDog in Facebook.
ADMIN UUMV
PSA – If you are ever lost while hiking, get stranded with a broken down car, etc and you notice your cell phone is either low on juice or has no signal, here is a tip that very well may save your life.
Change the voicemail on your phone to a message that gives your approximate location, the time, the date, your situation (lost, out of gas, car broken down, injured, etc) and any special instructions such as you are staying with the car, you are walking toward a town, etc…. The best part of this is that even if your cell phone dies or stops working, voicemail still works, so anyone calling your phone looking for you will hear the message and know where to find you or where to send help.