TDD в Laravel с использованием phpunit для разработки REST Api

Начните работу с TDD в Laravel, используя phpunit для разработки REST Api. В качестве примера мы рассмотрим создание API с использованием подхода TDD, чтобы позволить пользователю обновлять свой профиль.

TDD подход

Идея подхода TDD заключается в том, чтобы сначала создать тестовый пример, прежде чем писать фактический код. Таким образом, написание кода API становится легким, если вы уже поняли все, что вы будете делать в API во время написания тестового примера.

После того, как у вас есть тестовый пример, после каждого изменения в API вы можете проверить, работает ли ваш API должным образом, запустив тестовый пример.

Переменные среды

Если вы посмотрите на phpunit.xml. Вы увидите переменные среды, определенные следующим образом.

    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <server name="DB_CONNECTION" value="sqlite"/>
        <server name="DB_DATABASE" value=":memory:"/>
        <server name="MAIL_MAILER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
    </php>

Эти переменные среды используются при выполнении тестовых случаев. Laravel автоматически установит переменные среды, определенные в этом файле.

Здесь следует отметить, что мы используем в памяти базу данных sqlite. Преимущество использования базы данных в памяти заключается в том, что она автоматически создается в памяти при запуске тестов и автоматически удаляется после завершения тестовых случаев. Это не повлияет на вашу фактическую используемую базу данных. Вы можете настроить эти переменные среды в соответствии с вашими требованиями.

Создание теста

Откройте файл TestCase. Нам нужно будет внести некоторые изменения здесь, чтобы перенести и заполнить базу данных перед тестовым случаем. Для этого переопределите функцию setUp следующим образом.

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Foundation\Testing\WithFaker;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication, WithFaker;

    protected function setUp(): void {
        parent::setUp();

        $this->artisan('migrate');
        $this->artisan('db:seed');

        $this->withoutExceptionHandling(); //To get the actual Exception whenever it occurs instead of Laravel handing the exception.

    }
}

Создадим новый тест с помощью команды:

php artisan make:test UserTest

Откройте Tests/Feature/UsersTest.php

Напишите свой первый тестовый пример следующим образом:

<?php

namespace Tests\Feature;

use App\User;
use Tests\TestCase;
use JWTAuth;

class UsersTest extends TestCase
{
    /** @test */
    public function a_user_can_edit_his_profile() {
        $user = User::first();

        $token = JWTAuth::fromUser($user);

        $attributes = ['name' => $this->faker->name];

        $this->patchJson('api/user/profile', $attributes, ['authorization' => "bearer $token"])
            ->assertStatus(200);

        $this->assertDatabaseHas($user->getTable(), array_merge($attributes, [
            'id' => $user->id
        ]));
    }
}

Здесь мы используем JWT, но вы можете изменить его в соответствии с пакетом, который вы используете для создания токена аутентификации.

Мы используем функцию assertDatabaseHas и передаем имя таблицы и данные, которые должны присутствовать, чтобы проверить, обновлен ли профиль в базе данных.

Теперь, если мы попытаемся запустить, это не удастся, потому что мы еще не создали маршрут API.

Создание роута и контроллера

Сделаем это в api.php

Route::patch('user/profile','UserController@updateProfile');

Создайте новый контроллер с помощью команды:

php artisan make:controller UserController

Напишите функцию updateProfile в UserController , чтобы позволить пользователю редактировать свой профиль следующим образом:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:api');
    }

    public function updateProfile() {
        $attributes = request()->validate(['name' => 'required|string']);

        auth()->user()->update($attributes);

        return response()->json(["msg" => "Profile successfully updated"]);
    }
}

Запуск теста

Попробуйте запустить тестовый пример еще раз, и на этот раз ваш тестовый пример должен пройти успешно.

Тестовый случай пройден

Вот и все!

Надеюсь, вы найдете это полезным!