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

212 lines
6.2 KiB
Markdown

# 🧩 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.
```php
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).
```php
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.
```php
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).
```php
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.
```php
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`).