Files
agent-unit-testing/docs/cakephp/02-cakephp-components-guide.md
T
Pham-Tan-Thien 7425b263d5 feat: add comprehensive unit testing support for CakePHP
- Add 4 CakePHP Claude Code skills: cakephp-unit-test, cakephp-test-setup, cakephp-test-review, cakephp-mock-helper
- Add 11 CakePHP PHPUnit component templates (Table, Entity, Controller, Service, Command, Component, Middleware, Mailer, Form, Behavior, Helper)
- Add CakePHP configs (phpunit.xml.dist, app_local.test.php for SQLite in-memory)
- Add comprehensive CakePHP documentation and component guides
- Update test-runner.sh and installer to auto-detect Laravel and CakePHP
- Add CakePHP CI/CD templates for GitHub Actions and GitLab CI
- Update system prompt, verification checklist, and README with dedicated guides
2026-09-14 10:19:40 +07:00

6.2 KiB

🧩 CakePHP Components Unit Testing Reference

Hướng dẫn chi tiết cách viết test cho từng tầng thành phần trong CakePHP (Table, Entity, Controller, Service, Command, Component, Middleware, Mailer, Form, Behavior).


1. Table Classes (src/Model/Table/*Table.php)

  • Base Class: Cake\TestSuite\TestCase
  • Các điểm cần test:
    • validationDefault(): Đầu vào hợp lệ, thiếu trường bắt buộc, sai format (email, regex, số âm).
    • buildRules(): Quy tắc toàn vẹn dữ liệu (isUnique, existsIn).
    • Custom Finders (findPublished(), findAuth()): Truy vấn trả về đúng bản ghi mong muốn.
    • Custom methods: Xử lý nghiệp vụ lưu dữ liệu.
namespace App\Test\TestCase\Model\Table;

use App\Model\Table\ArticlesTable;
use Cake\TestSuite\TestCase;

class ArticlesTableTest extends TestCase
{
    protected ArticlesTable $Articles;
    protected array $fixtures = ['app.Articles'];

    protected function setUp(): void
    {
        parent::setUp();
        $this->Articles = $this->getTableLocator()->get('Articles');
    }

    public function testFindPublished(): void
    {
        $query = $this->Articles->find('published');
        $this->assertInstanceOf(\Cake\ORM\Query::class, $query);
        $result = $query->toArray();
        $this->assertNotEmpty($result);
        foreach ($result as $article) {
            $this->assertTrue($article->published);
        }
    }
}

2. Entity Classes (src/Model/Entity/*.php)

  • Base Class: Cake\TestSuite\TestCase
  • Các điểm cần test:
    • _setPassword() (Hashing logic).
    • Virtual Fields (_getFullName()).
    • $_accessible properties (Bảo vệ Mass Assignment).
namespace App\Test\TestCase\Model\Entity;

use App\Model\Entity\User;
use Cake\TestSuite\TestCase;

class UserTest extends TestCase
{
    public function testPasswordIsHashed(): void
    {
        $user = new User(['password' => 'secret123']);
        $this->assertNotEquals('secret123', $user->password);
        $this->assertTrue((new \Authentication\PasswordHasher\DefaultPasswordHasher())->check('secret123', $user->password));
    }

    public function testVirtualFieldFullName(): void
    {
        $user = new User(['first_name' => 'John', 'last_name' => 'Doe']);
        $this->assertSame('John Doe', $user->full_name);
    }
}

3. Controller Classes (src/Controller/*Controller.php)

  • Base Class: Cake\TestSuite\TestCase với Cake\TestSuite\IntegrationTestTrait
  • Các điểm cần test:
    • HTTP Status: 200 OK, 302 Redirect, 403 Forbidden, 404 Not Found, 422 Unprocessable Entity.
    • Flash messages: $this->assertFlashMessage().
    • Session & Auth: Giả lập đăng nhập qua $this->session().
    • CSRF & Security Tokens: Bắt buộc dùng $this->enableCsrfToken() và $this->enableSecurityToken() khi test POST/PUT/DELETE.
namespace App\Test\TestCase\Controller;

use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;

class ArticlesControllerTest extends TestCase
{
    use IntegrationTestTrait;
    protected array $fixtures = ['app.Articles', 'app.Users'];

    public function testAddWithoutAuthRedirectsToLogin(): void
    {
        $this->get('/articles/add');
        $this->assertRedirectContains('/login');
    }

    public function testAddSuccess(): void
    {
        $this->session(['Auth.User.id' => 1]);
        $this->enableCsrfToken();
        $this->enableSecurityToken();

        $this->post('/articles/add', [
            'title' => 'Sample Article',
            'body' => 'Body text',
            'published' => true,
        ]);

        $this->assertRedirect(['action' => 'index']);
        $this->assertFlashMessage('The article has been saved.');
    }
}

4. Service Classes (src/Service/*.php)

  • Base Class: Cake\TestSuite\TestCase
  • Các điểm cần test:
    • Các dependency được mock bằng PHPUnit Mock hoặc Mockery.
    • Kiểm thử toàn bộ các nhánh rẽ điều kiện (Success, Invalid Data, 3rd-Party Failure).
namespace App\Test\TestCase\Service;

use App\Service\PaymentProcessingService;
use Cake\TestSuite\TestCase;

class PaymentProcessingServiceTest extends TestCase
{
    public function testChargeSuccess(): void
    {
        $clientMock = $this->createMock(\App\External\StripeClient::class);
        $clientMock->expects($this->once())
            ->method('createCharge')
            ->willReturn(['id' => 'ch_123', 'status' => 'succeeded']);

        $service = new PaymentProcessingService($clientMock);
        $result = $service->processOrder(100.0, 'tok_visa');

        $this->assertTrue($result->isSuccess());
    }
}

5. Console Command Classes (src/Command/*Command.php)

  • Base Class: Cake\TestSuite\TestCase với Cake\Console\TestSuite\ConsoleIntegrationTestTrait
  • Các điểm cần test:
    • assertExitSuccess() và assertExitError().
    • assertOutputContains().
    • Arguments và Options flags.
namespace App\Test\TestCase\Command;

use Cake\Console\TestSuite\ConsoleIntegrationTestTrait;
use Cake\TestSuite\TestCase;

class SyncInventoryCommandTest extends TestCase
{
    use ConsoleIntegrationTestTrait;

    protected function setUp(): void
    {
        parent::setUp();
        $this->useCommandRunner();
    }

    public function testSyncAll(): void
    {
        $this->exec('sync_inventory --all');
        $this->assertExitSuccess();
        $this->assertOutputContains('Inventory sync completed.');
    }
}

6. Controller Component Classes (src/Controller/Component/*.php)

  • Test logic tái sử dụng gắn vào Controller, dùng ComponentRegistry.

7. Middleware Classes (src/Middleware/*.php)

  • Test PSR-15 Middleware với Cake\Http\ServerRequest và Response Handler.

8. Mailer Classes (src/Mailer/*Mailer.php)

  • Sử dụng Cake\TestSuite\EmailTrait, kiểm tra email recipient, subject, và template body.

9. Form Classes (src/Form/*Form.php)

  • Test standalone forms không gắn với ORM table (ContactForm, SearchFilterForm).
  • Kiểm tra validationDefault() và _execute().

10. Behavior Classes (src/Model/Behavior/*.php)

  • Test ORM Behavior hooks (beforeSave, beforeFind, afterSave).