ทดสอบว่าใช้งานได้จริง — แม่แบบ 4 เคส + กับดักตอนรันในเครื่อง
ชุดทดสอบที่ใช้พิสูจน์จริงกับ service ตัวแรก คัดลอกไปใช้ได้เลย · รวมกับดักที่ทำให้ 'ทดสอบผ่าน' ทั้งที่ระบบป้องกันปิดอยู่ และรายการอุบัติเหตุตอนรันในเครื่องที่เสียเวลาซ้ำ ๆ
อัปเดต: 2026-08-23
ทุกบรรทัดในหน้านี้มาจากการรันจริงกับ service ตัวแรกที่ทำเสร็จ ไม่ใช่แบบฝึกหัดที่แต่งขึ้น
1. 🔴 กับดักใหญ่ที่สุด: ผลที่ดูเหมือนผ่าน ทั้งที่ระบบยังปิดอยู่
ตอนทดสอบจริงเจอเหตุการณ์นี้: ยิงคำขอ ที่ไม่ได้เซ็น แล้วได้ 200 — ซึ่ง “ดูเหมือนระบบทำงานปกติ”
ความจริงคือ สวิตช์ยังไม่เปิด ⇒ ทุกคำขอผ่านหมดไม่ว่าจะเซ็นหรือไม่เซ็น ถ้ารายงานตอนนั้นก็จะเป็นการรายงานว่า “ทดสอบผ่าน” ทั้งที่ยังไม่มีการป้องกันอะไรเลย
กฎที่ได้จากเหตุการณ์นี้:
เคสลบได้ 200 → ไม่ใช่ "ผ่าน" แต่แปลว่า "การป้องกันปิดอยู่" → หยุด ไปเปิดสวิตช์ก่อน
และหลังเปลี่ยนค่าสวิตช์ ต้อง restart จริง (ค่าถูกอ่านครั้งเดียวตอน start) — พร้อมทั้ง ตรวจว่า process เก่าตายจริง ด้วยการ probe port ไม่ใช่เชื่อว่าสั่งหยุดแล้วมันหยุด
2. แม่แบบ 4 เคส (ทำตามลำดับนี้)
| # | เคส | ยิงยังไง | ต้องได้ |
|---|---|---|---|
| 0 | ลงทะเบียนกุญแจ | POST {base}/v1/client-keys พร้อม token | 200 + สถานะ Registered |
| 1 | เคสบวก — เซ็นถูก | GET {base}/v1/client-keys/ping + X-Timestamp + X-Signature | 200 |
| 2 | เคสลบ — ไม่เซ็น แต่ token ถูก | GET .../ping + token อย่างเดียว | 401 + SIG_MISSING_HEADER |
| 3 | เส้นยกเว้น | GET {base}/v1/security/jwks ไม่เซ็น | ต้องได้ error ทางธุรกิจหรือผลปกติ ไม่ใช่ 401 SIG_* |
| 4 | เคสควบคุม — ไม่มี header อะไรเลย | GET .../ping เปล่า ๆ | 401 แบบ หน้าตาต่างจากข้อ 2 อย่างชัดเจน |
ทำไมต้องมีข้อ 4: มันพิสูจน์ว่าการเพิ่มชั้นลายเซ็น ไม่ได้ทำให้ชั้น authentication เดิมหลวมลง — ถ้าข้อ 2 กับข้อ 4 ให้ผลหน้าตาเหมือนกันเป๊ะ แปลว่าคุณอาจกำลังวัดชั้นเดียว ไม่ใช่สองชั้น
ทำไมเคสบวกต้องมาก่อน: ชุดทดสอบที่มีแต่เคสลบจะเขียวสนิทแม้ระบบจะปฏิเสธทุกคนโดยผิดพลาด (เจอมาแล้ว 2 service ในเรื่อง API key)
3. หลักฐานที่ต้องเก็บ
ต่อ 1 เคส: คำสั่งจริง + HTTP status + เนื้อหาที่ตอบกลับแบบย่อ + เวลา · ห้ามสรุปแทนตัวเลข ห้ามใช้ผลรันเก่า
curl -s -o /dev/null -w '%{http_code}\n' "$BASE/v1/client-keys/ping" -H "Authorization: Bearer $TOKEN"
รวมถึงเก็บ commit ที่ทดสอบ ไว้ด้วย:
git rev-parse HEAD # ทดสอบบน commit ไหน ต้องบอกได้เสมอ
4. กับดักตอนรันในเครื่อง (แต่ละข้อมาจากอุบัติเหตุจริง)
| กับดัก | อาการ | วิธีที่ถูก |
|---|---|---|
dotnet user-secrets clear | secret ของทุก worktree หายพร้อมกัน (ใช้ไฟล์เดียวกัน) แล้ว boot ครั้งถัดไปพังแบบหาสาเหตุไม่เจอ | ลบทีละ key ด้วย remove เท่านั้น |
| ตั้ง environment ด้วย argument | --environment Development / --launch-profile ไม่ติด ⇒ ระบบคิดว่าเป็น Production ⇒ ไม่โหลด user-secrets ทั้งก้อน | ใช้ env var: ASPNETCORE_ENVIRONMENT=Development dotnet run |
| ค่าจาก KeyVault ทับ config ในเครื่อง | ตั้ง Redis/ServiceBus ไว้ในเครื่องแล้วแต่แอปไปต่อของ cloud | รู้ไว้ว่า env var จาก KeyVault ชนะทุกชั้น — ตรวจค่าจริงที่แอปเห็นตอน start |
| ลืมเคลียร์ connection string ของ ServiceBus | boot ค้าง/ช้าเป็นนาที | เคลียร์ ทุกครั้ง ก่อน boot ไม่ใช่ครั้งเดียวจบ |
| กุญแจเข้ารหัสถูก generate ใหม่ทุกครั้ง | ข้อมูลที่เข้ารหัสไว้รอบก่อนถอดไม่ได้ | ตั้งครั้งเดียวแล้วเก็บถาวรในเครื่อง |
ลงทะเบียนกุญแจซ้ำได้ 409 | คิดว่าพัง | เป็นพฤติกรรมที่ถูก (กุญแจเดิมอายุ 7 วัน) ใช้ผู้ใช้ทดสอบคนใหม่หรือรอหมดอายุ |
curl บน Git Bash | path /api/... ถูกแปลงเป็น path แบบ Windows เงียบ ๆ ⇒ ลายเซ็นเพี้ยน | นำหน้าด้วย MSYS_NO_PATHCONV=1 |
| สั่งหยุด process แล้วเชื่อว่าหยุด | boot ใหม่ไปชนตัวเก่าที่ยังถือ port อยู่ แล้วทดสอบโค้ดเวอร์ชันเก่า | probe port จริงก่อน boot รอบใหม่เสมอ |
5. ก่อนบอกว่า “เสร็จแล้ว”
dotnet build -c Release # ต้อง 0 error (CI ใช้ Release และเปิด analyzer เป็น error)
dotnet test -c Release # ต้อง 0 failed และต้องบอกจำนวนที่ผ่านได้
- อย่ารันชุดทดสอบ 2 ชุดพร้อมกันแล้วเอาตัวเลขมารายงานปนกัน
- ถ้าแก้ระบบป้องกันแล้วจำนวน test ที่ผ่าน ไม่เปลี่ยนเลย ให้สงสัยว่ายังไม่ได้ทดสอบสิ่งที่คิดว่าทดสอบ — ลองปิดโค้ดป้องกันดู test ต้องแดง ถ้ายังเขียวแปลว่าชุดทดสอบไม่ได้ตรวจของจริง
- ทุกคำกล่าวว่า “ผ่าน” ต้องมาพร้อมผลรันจริง ไม่ใช่ “น่าจะผ่าน”