Mock & แยก dependency
เทสต์โค้ดที่พึ่งของภายนอก (API, DB, เวลา) โดยใช้ของปลอมแทน เพื่อให้เทสต์เร็วและเสถียร
เทสต์ที่ดีต้องเร็วและให้ผลเหมือนเดิมทุกครั้ง แต่ถ้าโค้ดไปยิง API จริงหรือแตะ DB จริง เทสต์จะช้าและไม่เสถียร (เน็ตหลุด, ข้อมูลเปลี่ยน) การ mock คือแทนของภายนอกด้วย "ของปลอม" ที่เราคุมได้
ทำไมต้อง mock
- เร็ว — ไม่ต้องรอ network จริง
- เสถียร — ผลไม่ขึ้นกับเซิร์ฟเวอร์/ข้อมูลภายนอก
- ทดสอบเคสยาก — จำลอง error เช่น API ล่ม, timeout ได้
- ไม่กระทบของจริง — ไม่เผลอลบข้อมูล/ส่งอีเมลจริงตอนเทสต์
mock การเรียก API
สมมติฟังก์ชันเราเรียก requests.get ไปดึงข้อมูล เราไม่อยากให้เทสต์ยิงเน็ตจริง จึงแทน requests.get ด้วย mock ที่คืนค่าที่เรากำหนด
# code.py
import requests
def get_user_name(user_id):
resp = requests.get(f"https://api.example.com/users/{user_id}")
return resp.json()["name"]# test_code.py
from unittest.mock import patch
from code import get_user_name
@patch("code.requests.get")
def test_get_user_name(mock_get):
# กำหนดให้ของปลอมคืนค่าที่เราต้องการ
mock_get.return_value.json.return_value = {"name": "Aph"}
assert get_user_name(1) == "Aph" # ไม่ยิงเน็ตจริง
mock_get.assert_called_once() # ตรวจว่าถูกเรียกจริงmonkeypatch — fixture ของ pytest
pytest มี fixture ชื่อ monkeypatch ใช้แทนค่า/ฟังก์ชันชั่วคราวระหว่างเทสต์ได้ง่าย เช่นแทนค่าเวลาหรือ env var
def get_mode():
import os
return os.environ.get("MODE", "dev")
def test_get_mode(monkeypatch):
monkeypatch.setenv("MODE", "prod") # ตั้ง env ชั่วคราว
assert get_mode() == "prod"
# พ้นเทสต์ค่าคืนเดิมอัตโนมัติเทสต์ที่ต้องต่อ network/DB จริงจะช้า ล้มเมื่อเน็ตหลุด และอาจกระทบข้อมูลจริง — แยก dependency ภายนอกออกด้วย mock ให้ unit test รันเดี่ยว ๆ เร็วและเสถียร (เก็บการต่อของจริงไว้ที่ integration test จำนวนน้อย)
สรุปหัวข้อนี้
- mock = แทนของภายนอก (API/DB/เวลา) ด้วยของปลอมที่คุมได้
- ทำให้เทสต์เร็ว เสถียร จำลอง error ได้ ไม่กระทบของจริง
- unittest.mock.patch แทนฟังก์ชัน + กำหนด return_value
- monkeypatch (pytest) แทนค่า/env ชั่วคราวในเทสต์
1) เขียนฟังก์ชันที่เรียก requests.get แล้ว mock ไม่ให้ยิงเน็ตจริง 2) ใช้ assert_called_once ตรวจว่าถูกเรียก 3) ใช้ monkeypatch.setenv แทน env var ในเทสต์ 4) อธิบายว่าทำไมไม่ควรให้ unit test ยิง API จริง