คู่มือพิมพ์เขียวเชิงลึกและการวิเคราะห์ทางเทคนิค: การจำลอง OAuth2/JWT Flow, การทำ Contract Testing ตรวจสอบโครงสร้าง Mocks ร่วมกับ OpenAPI Specification, การทำ Verification Assertions ใน CI/CD และการปรับแต่ง Netty Performance รองรับโหลด 15,000+ RPS
ชื่อบท/หัวข้อหลัก: Module 6: Enterprise Security, Contract Testing (OpenAPI), Verification Assertions & High-Throughput Load Testing
ตอบ: ในระบบระดับองค์กร (Enterprise) การทดสอบซอฟต์แวร์ไม่สามารถละเลยเรื่อง ความปลอดภัย (Security), การป้องกันสัญญา API คลาดเคลื่อน (Contract Drift) และ การรองรับภาระงานหนัก (High-Throughput Load Testing) บทนี้ตั้งชื่อว่า Enterprise Security, Contract Testing & Load Testing เพื่อเรียนรู้วิธีการจำลอง OAuth2/JWT Flow, การทำ Contract Testing ตรวจสอบโครงสร้าง Mocks ร่วมกับ OpenAPI/Swagger Specification, การทำ Verification Assertions ใน CI/CD Pipeline และการปรับแต่ง Netty Performance เพื่อใช้ MockServer รับมือทราฟฟิกทดสอบระดับหมื่น Requests Per Second (RPS) ได้อย่างมั่นคง
ระบบ Enterprise Banking Gateway กับวิกฤต API Drift และระบบ Load Test พังพินาศ
สถาบันการเงินแห่งหนึ่งกำลังเปิดตัวระบบ Open Banking API ที่ต้องเชื่อมต่อกับ FinTech Partners นับร้อยราย ระบบมีมาตรการความปลอดภัยเข้มงวดด้วย OAuth2/OIDC (JWT Bearer Token) และกำหนดสเปก API ไว้ในไฟล์ OpenAPI Specification (.yaml)
อย่างไรก็ตาม ในระหว่างการพัฒนาเกิดปัญหาใหญ่ 3 ประการ:
💡 การนำ Enterprise Security, Contract Testing & Netty Tuning เข้ามาแก้ปัญหา: ทีมงานนำ MockServer เข้ามาทำหน้าที่จำลอง OAuth2 Token Provider และตรวจจับสิทธิ์ JWT, นำไฟล์ OpenAPI Specification มาผูกเข้ากับ MockServer เพื่อทำ Contract Testing อัตโนมัติ (หาก Mocks ไม่ตรงกับ OpenAPI Spec จะถูกปฏิเสธทันที) และปรับแต่ง Netty Thread Pool / Memory Engine ของ MockServer ให้รองรับ Load Test ระดับ 15,000+ RPS ได้สบายๆ
แปลตรงตัว: การทดสอบการปฏิบัติตามสัญญาข้อตกลง API
อุปมาอุปไมย: เหมือน "การตรวจสอบพิมพ์เขียวก่อสร้าง" ไฟล์ OpenAPI/Swagger เปรียบเหมือนพิมพ์เขียวอาคาร Contract Testing คือการนำสถาปนิกมาสแกนดูว่า Mocks และ Request/Response ที่รับส่งกัน มีขนาด เสา และคาน ตรงตามพิมพ์เขียวเป๊ะๆ หรือไม่
แปลตรงตัว: การตรวจสอบความถูกต้องของสิทธิ์การเข้าถึงผ่าน JWT
อุปมาอุปไมย: เหมือน "ตั๋วคอนเสิร์ตระบุชื่อพร้อมตราประทับลายน้ำ" เจ้าหน้าที่ประตูด้านหน้า (MockServer) สามารถสแกนตรวจดูลายเซ็นดิจิทัลและวันหมดอายุได้ทันทีโดยไม่ต้องโทรไปถามผู้จัดการใหญ่ (Identity Provider) ทุกครั้ง
แปลตรงตัว: การตรวจสอบความยืนยันการทำงานหลังรัน Test Suite
อุปมาอุปไมย: เหมือน "ผู้ตรวจการบัญชี" ที่เข้ามาเปิดสมุดบันทึกหลังปิดงบ เพื่อยืนยันว่าทุกธุรกรรมยิงเข้ามาครบตามเงื่อนไขเป๊ะๆ ก่อนอนุญาตให้ผ่าน Pipeline
แปลตรงตัว: การปรับแต่งเอนจินเครือข่ายสำหรับภาระงานสูง
อุปมาอุปไมย: เหมือน "การขยายถนนและเพิ่มช่องจ่ายเงินทางด่วนเป็น 16 เลน" พร้อมปรับจูนแรมและ Thread Pool เพื่อให้รองรับรถ (Requests) นับหมื่นคันต่อวินาทีได้โดยไม่เกิดรถติดค้าง
เกิด API Contract Drift ระหว่างทีมพัฒนาเพราะไม่มีตัวตรวจสอบอัตโนมัติ และระบบ Mock ไม่ถูกปรับแต่งด้านประสิทธิภาพ (Tuning) ให้รองรับการทำ Load Testing
เกิด Breaking Changes บน Production, เสียเวลาในการขอ Security Token และไม่สามารถการันตีความสามารถในการรองรับภาระงานหนักของระบบได้ก่อนเปิดตัวจริง
type: OPENAPI)
{
"httpRequest": {
"method": "POST",
"path": "/api/v1/payments",
"body": {
"type": "OPENAPI", # [Line 5] ใช้เอนจินการตรวจจับแบบ OPENAPI
"specUrlOrPayload": "contracts/payment-spec.yaml", # [Line 6] ชี้ไปยังไฟล์ OpenAPI Specification (.yaml หรือ .json)
"operationId": "createPayment" # [Line 7] ระบุ operationId ที่นิยามไว้ใน OpenAPI Spec
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"status\": \"SUCCESS\", \"transactionId\": \"TX-998811\"}"
}
}
Authorization Bearer)
{
"httpRequest": {
"method": "GET",
"path": "/api/v1/secure-data",
"headers": {
"Authorization": ["Bearer eyJ[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+"]
# [Line 6] ใช้ Regex ตรวจจับโครงสร้าง JWT 3 ส่วน (Header.Payload.Signature) อย่างแม่นยำ
}
},
"httpResponse": {
"statusCode": 200,
"headers": { "Content-Type": ["application/json"] },
"body": "{\"data\": \"Confidential Enterprise Data\"}"
}
}
mockserver.properties)
# [Line 1] ปรับขนาด Thread Pool (Event Loop) สำหรับรองรับ Connection จำนวนมากพร้อมกัน
mockserver.nioEventLoopThreadCount=16
# [Line 3] ปรับขนาดแคชสำหรับเก็บบันทึก Logs ในหน่วยความจำ
mockserver.maxExpectations=5000
# [Line 5] ปิดการเก็บบันทึก Log ระดับย่อยในระหว่างทำ Load Test เพื่อประหยัด CPU และ RAM
mockserver.logLevel=WARN
เปิดเว็บเบราว์เซอร์ไปที่: http://localhost:1080/mockserver/dashboard
========================================================================================
MOCKSERVER WEB DASHBOARD (PORT 1080)
========================================================================================
[ Active Expectations ] | [ Recorded Requests / Logs ] | [ Breakpoints ] | [ Reset All ]
----------------------------------------------------------------------------------------
OpenAPI Matcher Status: - ในแท็บ Active Expectations ตรวจดูว่าข้อที่ผูกกับ OpenAPI Spec ขึ้นสถานะ Validated
Security Match Failures: - หาก Client ส่ง JWT Token ผิดรูปแบบ สามารถเปิดแท็บ Recorded Requests / Logs เพื่อดูจุดที่ Mismatch
High-Load Metrics: - ส่องดูความเร็วในการประมวลผลคำสั่ง Mocks เมื่อถูกยิงด้วย Load Test Tool (เช่น k6 หรือ Locust)
mockserver-module6-enterprise/
├── docker-compose.yml
├── config/
│ └── mockserver.properties # ปรับแต่ง Netty & High-Throughput Parameters
├── contracts/
│ └── payment-service-v1.yaml # ไฟล์ OpenAPI 3.0 Specification
├── expectations/
│ ├── security/
│ │ ├── oauth2-token-mock.json # จำลอง Endpoint ออก Token
│ │ └── jwt-protected-endpoint.json # ตรวจสอบ Bearer JWT
│ └── contracts/
│ └── openapi-contract-mock.json # Mocks ผูกกับ OpenAPI Spec
├── scripts/
│ ├── run_load_test.sh # สคริปต์รัน k6 Load Testing
│ └── seed_enterprise_mocks.sh
└── tests/
└── ContractAndSecurityTest.java
พิมพ์ฟีลด์ผิดเป็น trans_id แทน transactionId -> Test ผ่าน แต่ขึ้น Prod พัง:
{ "httpRequest": { "path": "/pay" }, "httpResponse": { "body": "{\"trans_id\": 123}" } }
ถ้าโครงสร้างไม่ตรงกับสเปก ระบบจะไม่อนุญาตให้ผ่านตั้งแต่ตอนเขียน Test:
{
"httpRequest": {
"path": "/pay",
"body": { "type": "OPENAPI", "specUrlOrPayload": "contracts/api.yaml", "operationId": "payOrder" }
}
}
ก่อนเริ่มทำ ตรวจสอบว่าเปิด MockServer ไว้ที่ http://localhost:1080 เรียบร้อยแล้ว
Setup:
curl -X PUT "http://localhost:1080/mockserver/expectation" -H "Content-Type: application/json" -d '{"httpRequest": { "method": "POST", "path": "/api/v1/payments", "body": { "type": "JSON_SCHEMA", "jsonSchema": "{\"type\": \"object\", \"properties\": {\"amount\": {\"type\": \"number\"}}, \"required\": [\"amount\"]}" } }, "httpResponse": { "statusCode": 200, "headers": { "Content-Type": ["application/json"] }, "body": "{\"status\": \"SUCCESS\"}" }}'
Test: curl -i -X POST http://localhost:1080/api/v1/payments -H "Content-Type: application/json" -d '{"amount": 1500.50}' (ได้ 200 OK)
Setup:
curl -X PUT "http://localhost:1080/mockserver/expectation" -H "Content-Type: application/json" -d '{"httpRequest": { "method": "GET", "path": "/api/v1/secure-data", "headers": { "Authorization": ["Bearer eyJ[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+"] } }, "httpResponse": { "statusCode": 200, "headers": { "Content-Type": ["application/json"] }, "body": "{\"data\": \"SECURE_CONTENT\"}" }}'
Test: curl -i http://localhost:1080/api/v1/secure-data -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.s6K73N_A" (ได้ 200 OK)
Action: ยิง 3 ครั้ง:
curl -X POST http://localhost:1080/api/v1/audit -d '{"event": "1"}'
curl -X POST http://localhost:1080/api/v1/audit -d '{"event": "2"}'
curl -X POST http://localhost:1080/api/v1/audit -d '{"event": "3"}'
Verify (ระหว่าง 2 ถึง 5 ครั้ง): curl -X PUT "http://localhost:1080/mockserver/verify" -H "Content-Type: application/json" -d '{"httpRequest": { "method": "POST", "path": "/api/v1/audit" }, "times": { "atLeast": 2, "atMost": 5 }}' (ได้ HTTP 202 Accepted)
Setup:
curl -X PUT "http://localhost:1080/mockserver/expectation" -H "Content-Type: application/json" -d '{"httpRequest": { "method": "POST", "path": "/oauth/token", "body": { "type": "PARAMETERS", "parameters": { "grant_type": ["client_credentials"] } } }, "httpResponse": { "statusCode": 200, "headers": { "Content-Type": ["application/json"] }, "body": "{\"access_token\": \"mocked-jwt-token-xyz\", \"token_type\": \"Bearer\", \"expires_in\": 3600}" }}'
Test: curl -i -X POST http://localhost:1080/oauth/token -d "grant_type=client_credentials" (ได้ 200 OK พร้อม Access Token)
Test (ยิงขนานรวดเร็ว 10 ครั้ง):
for i in {1..10}; do curl -s http://localhost:1080/api/v1/health > /dev/null & done; wait
Expected: ทุก Request ได้รับคำตอบสมบูรณ์โดยไม่มี Connection Drop
Action:
curl -X PUT "http://localhost:1080/mockserver/reset"
Expected: ระบบล้างข้อมูลพร้อมเริ่มรอบถัดไป
คลิกเลือกคำตอบข้อที่ถูกต้อง ระบบจะตรวจให้คะแนนและแสดงผลเฉลยพร้อมคำอธิบายทันที!
คะแนนของคุณคือ ...
เนื้อหาและแบบฝึกหัดทั้งหมดในวันนี้ ตอบและสะท้อนชื่อบท Day 6 / Module 6: Enterprise Security, Contract Testing & Load Testing อย่างสมบูรณ์: การใช้ OpenAPI Contract Testing ช่วยปิดรอยรั่ว API Drift, การจำลอง OAuth2/JWT Security ช่วยให้การทดสอบระบบความปลอดภัยราบรื่น, การใช้ Verification Assertions ช่วยการันตีความถูกต้องใน CI/CD Pipeline และการปรับแต่ง Netty Engine ก็ทำให้ MockServer พร้อมลุยศึกหนักในระดับ Enterprise Load Testing ได้อย่างมั่นใจครับ! ครบถ้วนสมบูรณ์ทั้ง 6 โมดูลตามหลักสูตร MockServer Professional Mastery แล้วครับ!