سرفصل‌های آموزشی
آموزش RESTful API
تست کردن DefaultController با استفاده از یونیت تست

تست کردن DefaultController با استفاده از یونیت تست

به همان روشی که اقدام به یونیت تست کردن UserController کردیم، حال در این آموزش قصد داریم اَکشن‌های موجود داخل DefaultController که جملگی مرتبط با عملیات CRUD در ارتباط با مقالات هستند را مورد آزمایش قرار دهیم. برای همین منظور، داخل پوشهٔ tests که پیش از این ساختیم یک فایل جدید با نامی بامسمی همچون DefaultControllerTest.php ساخته و آن را به صورت زیر تکمیل می‌کنیم:

<?php
use Api\Config\Database;
use Api\Models\Article;
use Api\Models\User;
use Firebase\JWT\JWT;
use PHPUnit\Framework\TestCase;

class DefaultControllerTest extends TestCase
{
    public function testGettingAnArticleById()
    {
        $sampleArticleId = 1;
        $articleModel = new Article((new Database())->connect());
        $result = $articleModel->readById($sampleArticleId);
        $result = $result->fetchAll(\PDO::FETCH_ASSOC);
        $this->assertIsArray($result);
    }

    public function testGettingAllArticles()
    {
        $articleModel = new Article((new Database())->connect());
        $result = $articleModel->read();
        $result = $result->fetchAll(\PDO::FETCH_ASSOC);
        $this->assertIsArray($result);
    }

    public function testCreatingANewArticle()
    {
        $tmpUserId = 1;
        $token = JWT::encode([
            'iat' => time(),
            'iss' => 'localhost',
            'exp' => time() + 60 * 60,
            'userId' => $tmpUserId,
        ], '8dc2d81404c4ca0ba23b85b941696534');
        $payload = JWT::decode($token, '8dc2d81404c4ca0ba23b85b941696534', ['HS256']);
        $user = new User((new Database())->connect());
        $result = $user->fetchUserById($payload->userId);
        $result = $result->fetchAll(\PDO::FETCH_ASSOC);
        if ($result) {
            $articleModel = new Article((new Database())->connect());
            $tmpParams = [
                'articleTitle' => 'Title',
                'articleContent' => 'Content',
                'usrId' => $tmpUserId,
                'catId' => 1,
            ];
            $isInserted = $articleModel->create($tmpParams);
            $this->assertTrue($isInserted);
        }
    }

    public function testUpdatingAnArticle()
    {
        $tmpUserId = 1;
        $tmpArticleId = 1;
        $token = JWT::encode([
            'iat' => time(),
            'iss' => 'localhost',
            'exp' => time() + 60 * 60,
            'userId' => $tmpUserId,
        ], '8dc2d81404c4ca0ba23b85b941696534');
        $payload = JWT::decode($token, '8dc2d81404c4ca0ba23b85b941696534', ['HS256']);
        $user = new User((new Database())->connect());
        $result = $user->fetchUserById($payload->userId);
        $result = $result->fetchAll(\PDO::FETCH_ASSOC);
        if ($result) {
            $articleModel = new Article((new Database())->connect());
            $tmpParams = [
                'articleTitle' => 'New article title',
                'articleContent' => 'new article content',
                'usrId' => $tmpUserId,
                'catId' => 2,
            ];
            $isUpdated = $articleModel->update($tmpArticleId, $tmpParams);
            $this->assertTrue($isUpdated);
        }
    }

    public function testDeletingAnArticle()
    {
        $tmpUserId = 1;
        $tmpArticleId = 10;
        $token = JWT::encode([
            'iat' => time(),
            'iss' => 'localhost',
            'exp' => time() + 60 * 60,
            'userId' => $tmpUserId,
        ], '8dc2d81404c4ca0ba23b85b941696534');
        $payload = JWT::decode($token, '8dc2d81404c4ca0ba23b85b941696534', ['HS256']);
        $user = new User((new Database())->connect());
        $result = $user->fetchUserById($payload->userId);
        $result = $result->fetchAll(\PDO::FETCH_ASSOC);
        if ($result) {
            $articleModel = new Article((new Database())->connect());
            $isDeleted = $articleModel->delete($tmpArticleId);
            $this->assertTrue($isDeleted);
        }
    }
}

پیش از تفسیر کدهای فوق،‌ ابتدا با استفاده از کامند vendor/bin/phpunit/. یک بار یونیت تست را اجرا می‌کنیم:

/var/www/rest-api-blog$ ./vendor/bin/phpunit 
PHPUnit 8.1.5 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.3.5-1+ubuntu18.04.1+deb.sury.org+1
Configuration: /var/www/rest-api-blog/phpunit.xml

.......  7 / 7 (100%)

Time: 134 ms, Memory: 4.00 MB

OK (7 tests, 7 assertions)

پیش از این داخل کلاس UserControllerTest دو تست نوشته بودیم و در کلاس جدید DefaultControllerTest نیز پنج تست مختلف نوشته‌ایم که جمعاً می‌شود هفت تست و خروجی نیز حاکی از آن است که هفت یونیت تست با موفقیت انجام شده‌اند.

در فانکشن ()testGettingAnArticleById قابلیت فِچ کردن یک مقاله بر اساس شناسه را تست کرده‌ایم و Assertion مورد استفاده نیز فانکشنی داخل فریمورک PHPUnit تحت عنوان ()assertIsArray است که چناچه پارامتر ورودی‌اش یک آرایه باشد، تست را پاس می‌کند و از آنجا که متغیر result$ یک آرایه می‌باشد، این تست به درستی پاس خواهد شد. فانکشن ()testGettingAllArticles نیز قابلیت فراخوانی تمام مقالات را تست می‌کند و تا حد بسیاری مشابه تست قبلی است.

در ادامه، تستی نوشته‌ایم به نام ()testCreatingANewArticle که قابلیت درج یک مقالهٔ جدید در دیتابیس را تست می‌کند بدین صورت که داخل آن یک شناسهٔ کاربری که حتماً می‌باید در جدول users وجود داشته باشد را داخل متغیری به نام tmpUserId$ ذخیره کرده سپس با استفاده از کلاس JWT یک توکن اِنکُود نموده و آن را داخل متغیر token$ ذخیره کرده‌ایم و مجدد این توکن را دیکُد کرده و مقدارش را داخل متغیر payload$ ریخته‌ایم. در ادامه یک کوئری به جدول users زده تا از وجود کاربری با شناسهٔ ۱ اطمینان حاصل کنیم و اگر چنین کاربری وجود داشت، وارد بلوک if شده و پس از ریختن یکسری دیتای دلخواه داخل آرایه‌ای به نام tmpParams$، متد ()create از کلاس Article را فراخوانی کرده و نتیجه‌اش را داخل متغیری به نام isInserted$ ریخته‌ایم و در نهایت هم از فانکشن ()assertTrue استفاده کرده تا true بودن متغیر isInserted$ را تست کنیم.

در تستی تحت عنوان ()testUpdatingAnArticle که به منظور آزمودن قابلیت به‌روزرسانی مقالات نوشته‌ایم، ساختار تا حد بسیاری مشابه تست قبلی است با این تفاوت که در آن یک متغیر جدید تحت عنوان tmpArticleId$ ساخته که قرار است شناسهٔ یک مقاله‌ای که پیش از این در دیتابیس به ثبت رسیده را در خود ذخیره سازد؛ سپس از متد ()update استفاده نموده‌، پارامترهای مورد نیاز را پاس داده و صحت عملکرد این متد را تست نموده‌ایم.

در نهایت هم به منظور حذف یک مقاله از جدول articles، متدی نوشته‌ایم به نام ()testDeletingAnArticle که در آن با فراخوانی متد ()delete از مُدل Article، سازوکار حذف یک مقاله از دیتابیس را تست نموده‌ایم.

online-support-icon