Functional test cho controller

Tạo bởi Hoàng Vũ, chỉnh sửa cuối lúc 12 tháng 5, 2025

Functional test (kiểm thử chức năng) kiểm tra tính năng hoàn chỉnh ở mức độ controller, như quá trình gửi request, xử lý logic và trả về response. Khác với unit test (kiểm tra từng đơn vị nhỏ), functional test sẽ mô phỏng request HTTP thật sự, sử dụng Symfony WebTestCase để kiểm tra toàn bộ luồng hoạt động của ứng dụng. Đây là bước quan trọng giúp bạn đảm bảo ứng dụng hoạt động đúng khi tích hợp nhiều thành phần với nhau.

1. Functional test là gì?

  • Là loại kiểm thử mô phỏng hành vi của người dùng hoặc client khi gửi HTTP request đến controller.
  • Kiểm tra route, logic xử lý, truy vấn dữ liệu, trả về view/json, v.v.
  • Giúp phát hiện lỗi khi nhiều thành phần (routing, service, entity...) kết hợp với nhau.

2. Cấu trúc test controller

  • Symfony cung cấp class WebTestCase trong gói symfony/framework-bundle.
composer require --dev symfony/test-pack

Cấu trúc file test thường nằm trong:

/tests/Controller

3. Tạo controller mẫu

// src/Controller/GreetingController.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class GreetingController
{
    #[Route('/hello/{name}', name: 'app_hello')]
    public function hello(string $name): Response
    {
        return new Response("Hello, $name");
    }
}

4. Viết functional test

// tests/Controller/GreetingControllerTest.php
namespace App\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class GreetingControllerTest extends WebTestCase
{
    public function testHelloRoute()
    {
        $client = static::createClient();
        $crawler = $client->request('GET', '/hello/John');

        $this->assertResponseIsSuccessful();
        $this->assertSelectorTextContains('body', 'Hello, John');
    }
}

Giải thích:

  • createClient() khởi tạo một client HTTP giả lập.
  • request() mô phỏng GET request.
  • assertResponseIsSuccessful() kiểm tra mã phản hồi HTTP (200).
  • assertSelectorTextContains() kiểm tra nội dung HTML.

5. Functional test với form

Giả sử bạn có form gửi dữ liệu:

// src/Controller/ContactController.php
#[Route('/contact', name: 'contact')]
public function contact(Request $request): Response
{
    if ($request->isMethod('POST')) {
        $data = $request->request->all();
        return new Response("Received: " . $data['name']);
    }

    return new Response('<form method="POST"><input name="name"><button>Send</button></form>');
}

Test POST request:

// tests/Controller/ContactControllerTest.php
public function testSubmitContactForm(): void
{
    $client = static::createClient();
    $crawler = $client->request('GET', '/contact');

    $form = $crawler->selectButton('Send')->form([
        'name' => 'Alice',
    ]);

    $client->submit($form);

    $this->assertResponseIsSuccessful();
    $this->assertSelectorTextContains('body', 'Received: Alice');
}

Ví dụ cụ thể: Test Controller trả JSON

// src/Controller/ApiController.php
#[Route('/api/user/{id}', name: 'api_user')]
public function getUser(int $id): JsonResponse
{
    return $this->json(['id' => $id, 'name' => 'User' . $id]);
}

Test JSON:

// tests/Controller/ApiControllerTest.php
public function testApiUserReturnsJson(): void
{
    $client = static::createClient();
    $client->request('GET', '/api/user/5');

    $this->assertResponseIsSuccessful();
    $this->assertJson($client->getResponse()->getContent());

    $data = json_decode($client->getResponse()->getContent(), true);
    $this->assertEquals(5, $data['id']);
    $this->assertEquals('User5', $data['name']);
}

Kết luận

Trong bài học này, bạn đã học:

  • Khái niệm functional test và cách viết test mô phỏng request đến controller.
  • Cách kiểm tra nội dung HTML, response status và phản hồi JSON.
  • Cách mô phỏng form gửi dữ liệu và kiểm tra đầu ra.

Functional test rất hữu ích trong giai đoạn cuối khi phát triển ứng dụng để kiểm tra toàn bộ tính năng từ đầu vào đến đầu ra. Trong bài tiếp theo, bạn sẽ học cách tối ưu ứng dụng với caching, logging và command line, để chuẩn bị triển khai ra môi trường thực tế.

Website Logo

Với hơn 10 năm kinh nghiệm lập trình web và từng làm việc với nhiều framework, ngôn ngữ như PHP, JavaScript, React, jQuery, CSS, HTML, CakePHP, Laravel..., tôi hy vọng những kiến thức được chia sẻ tại đây sẽ hữu ích và thiết thực cho các bạn.

Bình luận

Website Logo

Chào, tôi là Vũ. Đây là blog hướng dẫn lập trình của tôi.

Liên hệ công việc qua email dưới đây.

lhvuctu@gmail.com

Chúng Tôi Trên

Bạn đang muốn học về lập trình website?

Bạn cần nâng cao kiến thức chuyên nghiệp hơn để nâng cao cơ hội nghề nghiệp? Liên hệ