ศูนย์รวมความรู้วิศวกรรมซอฟต์แวร์

แบ่งปันประสบการณ์การออกแบบสถาปัตยกรรมระบบ, การเขียนโค้ดด้วย Laravel และการจัดการ Server ระดับ Production เพื่อยกระดับทักษะของนักพัฒนาทุกคน

เขียน Feature Test ใน Laravel สำหรับเชื่อมต่อ Oracle Database (บทที่ 1: การ Set Up ไฟล์และฐานข้อมูล)

เขียน Feature Test ใน Laravel สำหรับเชื่อมต่อ Oracle Database


 การเริ่มต้นเขียน Test สำหรับโปรเจกต์ที่มีความซับซ้อนอย่างการเชื่อมต่อ Oracle Database และมีระบบ Authentication (เช่น Keycloak) กั้นอยู่อาจดูเป็นเรื่องยาก บทความนี้จะพาไปตั้งไข่โครงสร้าง Feature Test แบบ Step-by-Step โดยเริ่มจากการจัดเตรียมไฟล์และ Set up สภาพแวดล้อมให้พร้อมก่อนลงมือเขียน Logic จริง
เป้าหมายของบทนี้: สามารถรัน Test เพื่อเชื่อมต่อกับ Oracle Database และวิ่งทะลุเข้า Controller ได้สำเร็จ โดยยังไม่ต้องคำนึงถึงการเช็คผลลัพธ์ (Assert) ในขั้นตอนนี้

1. สร้างไฟล์ Test ไว้ที่ไหนดี?
ใน Laravel เราจะสร้างไฟล์ทดสอบไว้ที่: tests/Feature/Stock/SampleControllerStoreTest.php

เหตุผลที่เราใช้โครงสร้างนี้:
  • ทำไมต้อง Feature? เพราะเราต้องการจำลองการยิง HTTP Request และเชื่อมต่อกับระบบฐานข้อมูลจริง ซึ่งต่างจาก Unit Test ที่มักจะแยกส่วนการทำงาน
  • ทำไมต้องมีโฟลเดอร์ Stock? การจัดกลุ่มไฟล์ Test ตาม Domain หรือ Module (เช่น Stock) จะช่วยให้โปรเจกต์ที่เป็นสเกลใหญ่เป็นระเบียบและค้นหาไฟล์ได้ง่ายขึ้น

2. โครงสร้างไฟล์ขั้นต่ำ (Minimal Pattern)
นี่คือโครงสร้างพื้นฐานที่คุณสามารถจำไปใช้เป็น Pattern เริ่มต้นได้เลย:
<?php

namespace Tests\Feature\Stock;

use Tests\TestCase;
use App\Models\User;
use App\Models\Scheme;
use Illuminate\Support\Facades\DB;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class SampleControllerStoreTest extends TestCase
{
    use DatabaseTransactions;

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

        // ขั้นตอนสำคัญ — เราจะมาตั้งค่าการเชื่อมต่อ DB และ Middleware กันที่นี่
    }

    public function test_store_creates_inventory_and_redirects_to_edit(): void
    {
        // บทถัดไป: เราจะมาเขียน Arrange → Act → Assert กัน
        $this->markTestIncomplete('ยังไม่เขียน logic — รอบทที่ 2');
    }
}


จุดสำคัญที่ต้องทำความเข้าใจ
โค้ด                           | ความหมายและหน้าที่
extends TestCase      | ต้องใช้ TestCase ของ Laravel (มีฟีเจอร์ HTTP, DB, Auth) ไม่ใช่ TestCase เพียวๆ ของ PHPUnit
DatabaseTransactions  | เปิด Transaction ตอนเริ่มเทส และ Rollback กลับตอนจบ ป้องกันไม่ให้ข้อมูลขยะค้างใน Oracle
setUp()                    | ฟังก์ชันที่จะถูกรัน ก่อน ทุกๆ Test Method เหมาะสำหรับใช้ตั้งค่า Environment
markTestIncomplete   | บอก PHPUnit ว่าเทสนี้ "ยังไม่เสร็จ" (Incomplete) จะไม่ถูกมองว่าเป็น Fail

3. เจาะลึกการตั้งค่าใน setUp()
ภายในฟังก์ชัน setUp() สำหรับเคสนี้ เราจะต้องจัดการ 2 เรื่องหลักๆ เพื่อให้ระบบพร้อมทดสอบ:

A) บังคับใช้ Oracle Database (ทับค่าใน phpunit.xml)
โดยปกติไฟล์ phpunit.xml มักจะถูกตั้งค่าให้ใช้ SQLite ในหน่วยความจำเพื่อความรวดเร็ว:
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>


หากเราไม่ทับค่านี้ เทสจะวิ่งไปหา SQLite ว่างๆ และทำให้เกิด Error เราจึงต้องเพิ่มคำสั่งเหล่านี้เข้าไปใน setUp():
config(['database.default' => 'oracle']);
DB::purge();              // ทิ้ง connection เก่าที่จำอยู่ใน memory
DB::reconnect('oracle');  // เชื่อมต่อใหม่ด้วย config ของ oracle จากไฟล์ .env

ข้อควรระวัง: ลำดับการเรียกใช้สำคัญมาก ต้องทำตามลำดับ config → purge → reconnect เสมอ

B) ปิดการทำงานของ Middleware (Bypass Authentication)
เนื่องจาก Route ของระบบ Stock มักจะถูกครอบด้วย auth:web หรือ Middleware อย่าง Keycloak ในการเขียนเทสเบื้องต้นที่เรายังไม่ต้องการจำลองการ Login ผ่าน Browser เราสามารถข้ามด่านนี้ไปก่อนได้ด้วยคำสั่ง:
$this->withoutMiddleware();

4. รวมโค้ด setUp() ฉบับสมบูรณ์
เมื่อนำทั้งสองส่วนมารวมกัน ฟังก์ชัน setUp() ของเราจะหน้าตาเป็นแบบนี้:
protected function setUp(): void
{
    parent::setUp(); // บังคับ: ต้องเรียก parent ก่อนเสมอ

    // 1. บังคับเชื่อมต่อ Oracle
    config(['database.default' => 'oracle']);
    DB::purge();
    DB::reconnect('oracle');

    // 2. ปิดกั้นด่าน Authentication ชั่วคราว
    $this->withoutMiddleware();
}


5. ทดสอบรันและเช็คความถูกต้อง (Concept Check)
มาทดสอบดูกันว่าโครงสร้างที่เราเตรียมไว้ทำงานได้หรือไม่ โดยรันคำสั่ง:
php artisan test --filter=SampleControllerStoreTest

ผลลัพธ์ที่คาดหวัง:
  • ระบบควรแสดงสถานะเป็น I (Incomplete) ไม่ใช่ตัวอักษรสีแดงที่ฟ้อง Error เรื่อง Class หรือ Namespace
  • สิ่งนี้แปลว่า: โหลดไฟล์สำเร็จ และคำสั่งใน setUp() ทำงานได้ราบรื่น

หากเกิด Error สีแดง: ถ้า Error ระบุปัญหาเกี่ยวกับการเชื่อมต่อ Oracle แสดงว่าเครื่องอาจจะเชื่อมต่อกับ Database Server ไม่ได้ หรือ Credential ในไฟล์ .env ไม่ถูกต้อง (ซึ่งเป็นเรื่องของ Environment ไม่ใช่ Logic ของเทสเราพัง)

สิ่งที่เรายัง "ไม่ได้ทำ" ในบทนี้
เพื่อโฟกัสทีละเรื่อง ในบทนี้เรายังละเว้นสิ่งเหล่านี้ไว้ก่อน:
  • ยังไม่มีการยิง Request จริง (เช่น post('/stock/store'))
  • ยังไม่มีการดึงข้อมูล Model ต่างๆ เช่น User หรือ Scheme มาใช้
  • ยังไม่มีการเขียน Assert เพื่อตรวจสอบการ Redirect หรือเช็คข้อมูลใน Database
ในบทถัดไป เราจะมาเริ่มลงมือเขียน Action และเช็คผลลัพธ์ (Arrange → Act → Assert) กันครับ!


laravel