เรียนรู้วิธีการใช้ฟังก์ชันจำลองอย่างมีประสิทธิภาพในกลยุทธ์การทดสอบของคุณเพื่อการพัฒนาซอฟต์แวร์ที่แข็งแกร่งและเชื่อถือได้ คู่มือนี้ครอบคลุมการใช้งานพร้อมตัวอย่าง
ฟังก์ชันจำลอง (Mock Functions): คู่มือฉบับสมบูรณ์สำหรับนักพัฒนา
ในโลกของการพัฒนาซอฟต์แวร์ การเขียนโค้ดที่แข็งแกร่งและเชื่อถือได้ถือเป็นสิ่งสำคัญอย่างยิ่ง การทดสอบอย่างละเอียดเป็นสิ่งสำคัญเพื่อให้บรรลุเป้าหมายนี้ โดยเฉพาะอย่างยิ่ง Unit testing ที่มุ่งเน้นการทดสอบส่วนประกอบหรือฟังก์ชันแต่ละส่วนแบบแยกเดี่ยว อย่างไรก็ตาม แอปพลิเคชันในโลกแห่งความเป็นจริงมักมีการพึ่งพาส่วนประกอบอื่นที่ซับซ้อน ทำให้การทดสอบแต่ละหน่วยแบบแยกเดี่ยวโดยสมบูรณ์เป็นเรื่องท้าทาย นี่คือจุดที่ฟังก์ชันจำลอง (mock functions) เข้ามามีบทบาท
ฟังก์ชันจำลอง (Mock Functions) คืออะไร?
ฟังก์ชันจำลองคือเวอร์ชันจำลองของฟังก์ชันจริงที่คุณสามารถใช้ในการทดสอบของคุณได้ แทนที่จะดำเนินการตามตรรกะของฟังก์ชันจริง ฟังก์ชันจำลองช่วยให้คุณสามารถควบคุมพฤติกรรมของมัน สังเกตวิธีการเรียกใช้งาน และกำหนดค่าที่จะส่งคืนได้ ฟังก์ชันเหล่านี้เป็นประเภทหนึ่งของ test double
ลองนึกภาพตามนี้: สมมติว่าคุณกำลังทดสอบเครื่องยนต์ของรถยนต์ (หน่วยที่กำลังทดสอบ) เครื่องยนต์ต้องอาศัยส่วนประกอบอื่นๆ เช่น ระบบหัวฉีดน้ำมันและระบบระบายความร้อน แทนที่จะใช้ระบบหัวฉีดและระบบระบายความร้อนจริงระหว่างการทดสอบเครื่องยนต์ คุณสามารถใช้ระบบจำลองที่เลียนแบบพฤติกรรมของมันได้ วิธีนี้ช่วยให้คุณสามารถแยกการทดสอบเครื่องยนต์ออกมาและมุ่งเน้นไปที่ประสิทธิภาพของมันโดยเฉพาะ
ฟังก์ชันจำลองเป็นเครื่องมือที่ทรงพลังสำหรับ:
- การแยกส่วนประกอบ (Isolating Units): การลบการพึ่งพาส่วนประกอบภายนอกเพื่อมุ่งเน้นไปที่พฤติกรรมของฟังก์ชันหรือส่วนประกอบเดียว
- การควบคุมพฤติกรรม (Controlling Behavior): การกำหนดค่าคืนกลับที่เฉพาะเจาะจง การโยนข้อผิดพลาด หรือการดำเนินการตรรกะที่กำหนดเองระหว่างการทดสอบ
- การสังเกตการณ์ปฏิสัมพันธ์ (Observing Interactions): การติดตามจำนวนครั้งที่ฟังก์ชันถูกเรียกใช้งาน อาร์กิวเมนต์ที่ได้รับ และลำดับที่ถูกเรียก
- การจำลองกรณีพิเศษ (Simulating Edge Cases): การสร้างสถานการณ์ที่ทำซ้ำได้ยากหรือไม่สามารถทำได้ในสภาพแวดล้อมจริง (เช่น เครือข่ายล้มเหลว ข้อผิดพลาดของฐานข้อมูล) ได้อย่างง่ายดาย
ควรใช้ฟังก์ชันจำลองเมื่อใด
Mocks เป็นเครื่องมือที่มีประโยชน์ที่สุดในสถานการณ์เหล่านี้:1. การแยกส่วนประกอบที่มีการพึ่งพาภายนอก
เมื่อหน่วยที่กำลังทดสอบของคุณต้องพึ่งพาบริการภายนอก ฐานข้อมูล API หรือส่วนประกอบอื่นๆ การใช้ส่วนประกอบจริงระหว่างการทดสอบอาจทำให้เกิดปัญหาหลายประการ:
- การทดสอบที่ช้า: การพึ่งพาส่วนประกอบจริงอาจใช้เวลาในการตั้งค่าและดำเนินการนาน ซึ่งจะเพิ่มเวลาในการทดสอบอย่างมาก
- การทดสอบที่ไม่น่าเชื่อถือ: การพึ่งพาส่วนประกอบภายนอกอาจคาดเดาไม่ได้และมีแนวโน้มที่จะล้มเหลว ซึ่งนำไปสู่การทดสอบที่ไม่เสถียร (flaky tests)
- ความซับซ้อน: การจัดการและกำหนดค่าการพึ่งพาส่วนประกอบจริงอาจเพิ่มความซับซ้อนที่ไม่จำเป็นให้กับการตั้งค่าการทดสอบของคุณ
- ค่าใช้จ่าย: การใช้บริการภายนอกมักมีค่าใช้จ่าย โดยเฉพาะอย่างยิ่งสำหรับการทดสอบที่ครอบคลุม
ตัวอย่าง: ลองนึกภาพว่าคุณกำลังทดสอบฟังก์ชันที่ดึงข้อมูลผู้ใช้จาก API ระยะไกล แทนที่จะทำการเรียก API จริงระหว่างการทดสอบ คุณสามารถใช้ฟังก์ชันจำลองเพื่อจำลองการตอบสนองของ API ได้ ซึ่งช่วยให้คุณทดสอบตรรกะของฟังก์ชันโดยไม่ต้องพึ่งพาความพร้อมใช้งานหรือประสิทธิภาพของ API ภายนอก สิ่งนี้สำคัญอย่างยิ่งเมื่อ API มีการจำกัดอัตราการเรียก (rate limits) หรือมีค่าใช้จ่ายที่เกี่ยวข้องกับการร้องขอแต่ละครั้ง
2. การทดสอบปฏิสัมพันธ์ที่ซับซ้อน
ในบางกรณี หน่วยที่กำลังทดสอบของคุณอาจมีปฏิสัมพันธ์กับส่วนประกอบอื่นๆ ในรูปแบบที่ซับซ้อน ฟังก์ชันจำลองช่วยให้คุณสามารถสังเกตและตรวจสอบปฏิสัมพันธ์เหล่านี้ได้
ตัวอย่าง: พิจารณาฟังก์ชันที่ประมวลผลธุรกรรมการชำระเงิน ฟังก์ชันนี้อาจมีปฏิสัมพันธ์กับเกตเวย์การชำระเงิน ฐานข้อมูล และบริการแจ้งเตือน การใช้ฟังก์ชันจำลองทำให้คุณสามารถตรวจสอบได้ว่าฟังก์ชันเรียกใช้เกตเวย์การชำระเงินด้วยรายละเอียดธุรกรรมที่ถูกต้อง อัปเดตฐานข้อมูลด้วยสถานะธุรกรรม และส่งการแจ้งเตือนไปยังผู้ใช้
3. การจำลองสภาวะข้อผิดพลาด
การทดสอบการจัดการข้อผิดพลาดเป็นสิ่งสำคัญเพื่อให้แน่ใจว่าแอปพลิเคชันของคุณมีความแข็งแกร่ง ฟังก์ชันจำลองช่วยให้สามารถจำลองสภาวะข้อผิดพลาดที่ทำซ้ำได้ยากหรือไม่สามารถทำได้ในสภาพแวดล้อมจริงได้อย่างง่ายดาย
ตัวอย่าง: สมมติว่าคุณกำลังทดสอบฟังก์ชันที่อัปโหลดไฟล์ไปยังบริการจัดเก็บข้อมูลบนคลาวด์ คุณสามารถใช้ฟังก์ชันจำลองเพื่อจำลองข้อผิดพลาดของเครือข่ายระหว่างกระบวนการอัปโหลดได้ ซึ่งช่วยให้คุณสามารถตรวจสอบได้ว่าฟังก์ชันจัดการข้อผิดพลาด ลองอัปโหลดใหม่ หรือแจ้งเตือนผู้ใช้ได้อย่างถูกต้อง
4. การทดสอบโค้ดแบบอะซิงโครนัส (Asynchronous Code)
โค้ดแบบอะซิงโครนัส เช่น โค้ดที่ใช้ callbacks, promises หรือ async/await อาจเป็นเรื่องท้าทายในการทดสอบ ฟังก์ชันจำลองสามารถช่วยคุณควบคุมเวลาและพฤติกรรมของการดำเนินการแบบอะซิงโครนัสได้
ตัวอย่าง: ลองนึกภาพว่าคุณกำลังทดสอบฟังก์ชันที่ดึงข้อมูลจากเซิร์ฟเวอร์โดยใช้การร้องขอแบบอะซิงโครนัส คุณสามารถใช้ฟังก์ชันจำลองเพื่อจำลองการตอบสนองของเซิร์ฟเวอร์และควบคุมเวลาที่การตอบสนองจะถูกส่งคืนได้ ซึ่งช่วยให้คุณทดสอบว่าฟังก์ชันจัดการกับสถานการณ์การตอบสนองที่แตกต่างกันและหมดเวลา (timeouts) อย่างไร
5. การป้องกันผลข้างเคียงที่ไม่พึงประสงค์
บางครั้ง การเรียกใช้ฟังก์ชันจริงระหว่างการทดสอบอาจมีผลข้างเคียงที่ไม่พึงประสงค์ เช่น การแก้ไขฐานข้อมูล การส่งอีเมล หรือการเรียกกระบวนการภายนอก ฟังก์ชันจำลองจะป้องกันผลข้างเคียงเหล่านี้โดยอนุญาตให้คุณแทนที่ฟังก์ชันจริงด้วยการจำลองที่ควบคุมได้
ตัวอย่าง: คุณกำลังทดสอบฟังก์ชันที่ส่งอีเมลต้อนรับไปยังผู้ใช้ใหม่ การใช้บริการอีเมลจำลองจะช่วยให้คุณมั่นใจได้ว่าฟังก์ชันการส่งอีเมลจะไม่ส่งอีเมลไปยังผู้ใช้จริงในระหว่างการรันชุดทดสอบของคุณ แต่คุณสามารถตรวจสอบได้ว่าฟังก์ชันพยายามส่งอีเมลพร้อมข้อมูลที่ถูกต้อง
วิธีใช้ฟังก์ชันจำลอง
ขั้นตอนเฉพาะสำหรับการใช้ฟังก์ชันจำลองขึ้นอยู่กับภาษาโปรแกรมและเฟรมเวิร์กการทดสอบที่คุณใช้ อย่างไรก็ตาม กระบวนการทั่วไปมักจะประกอบด้วยขั้นตอนต่อไปนี้:
- ระบุการพึ่งพา (Identify Dependencies): กำหนดว่าการพึ่งพาส่วนประกอบภายนอกใดที่คุณต้องการจำลอง
- สร้างอ็อบเจกต์จำลอง (Create Mock Objects): สร้างอ็อบเจกต์หรือฟังก์ชันจำลองเพื่อแทนที่การพึ่งพาส่วนประกอบจริง อ็อบเจกต์จำลองเหล่านี้มักจะมีคุณสมบัติเช่น `called`, `returnValue` และ `callArguments`
- กำหนดพฤติกรรมของ Mock (Configure Mock Behavior): กำหนดพฤติกรรมของฟังก์ชันจำลอง เช่น ค่าที่จะส่งคืน สภาวะข้อผิดพลาด และจำนวนครั้งที่เรียก
- ฉีด Mock เข้าไป (Inject Mocks): แทนที่การพึ่งพาส่วนประกอบจริงด้วยอ็อบเจกต์จำลองในหน่วยที่กำลังทดสอบของคุณ ซึ่งมักจะทำโดยใช้ Dependency Injection
- ดำเนินการทดสอบ (Execute Test): รันการทดสอบของคุณและสังเกตว่าหน่วยที่กำลังทดสอบมีปฏิสัมพันธ์กับฟังก์ชันจำลองอย่างไร
- ตรวจสอบปฏิสัมพันธ์ (Verify Interactions): ตรวจสอบว่าฟังก์ชันจำลองถูกเรียกด้วยอาร์กิวเมนต์ที่คาดหวัง ค่าคืนกลับ และจำนวนครั้งที่ถูกต้อง
- คืนค่าฟังก์ชันดั้งเดิม (Restore Original Functionality): หลังจากการทดสอบ ให้คืนค่าฟังก์ชันดั้งเดิมโดยการลบอ็อบเจกต์จำลองและกลับไปใช้การพึ่งพาส่วนประกอบจริง ซึ่งจะช่วยหลีกเลี่ยงผลข้างเคียงต่อการทดสอบอื่นๆ
ตัวอย่างฟังก์ชันจำลองในภาษาต่างๆ
นี่คือตัวอย่างของการใช้ฟังก์ชันจำลองในภาษาโปรแกรมและเฟรมเวิร์กการทดสอบที่ได้รับความนิยม:JavaScript กับ Jest
Jest เป็นเฟรมเวิร์กการทดสอบ JavaScript ที่ได้รับความนิยมซึ่งมีการรองรับฟังก์ชันจำลองในตัว
// ฟังก์ชันที่จะทดสอบ
function fetchData(callback) {
setTimeout(() => {
callback('Data from server');
}, 100);
}
// เคสทดสอบ
test('fetchData calls callback with correct data', (done) => {
const mockCallback = jest.fn();
fetchData(mockCallback);
setTimeout(() => {
expect(mockCallback).toHaveBeenCalledWith('Data from server');
done();
}, 200);
});
ในตัวอย่างนี้ `jest.fn()` จะสร้างฟังก์ชันจำลองที่มาแทนที่ฟังก์ชัน callback จริง การทดสอบจะตรวจสอบว่าฟังก์ชันจำลองถูกเรียกด้วยข้อมูลที่ถูกต้องโดยใช้ `toHaveBeenCalledWith()`
ตัวอย่างขั้นสูงที่ใช้โมดูล:
// user.js
import { getUserDataFromAPI } from './api';
export async function displayUserName(userId) {
const userData = await getUserDataFromAPI(userId);
return userData.name;
}
// api.js
export async function getUserDataFromAPI(userId) {
// จำลองการเรียก API
return new Promise(resolve => {
setTimeout(() => {
resolve({ id: userId, name: 'John Doe' });
}, 50);
});
}
// user.test.js
import { displayUserName } from './user';
import * as api from './api';
describe('displayUserName', () => {
it('should display the user name', async () => {
// จำลองฟังก์ชัน getUserDataFromAPI
const mockGetUserData = jest.spyOn(api, 'getUserDataFromAPI');
mockGetUserData.mockResolvedValue({ id: 123, name: 'Mocked Name' });
const userName = await displayUserName(123);
expect(userName).toBe('Mocked Name');
// คืนค่าฟังก์ชันดั้งเดิม
mockGetUserData.mockRestore();
});
});
ในที่นี้ `jest.spyOn` ถูกใช้เพื่อสร้างฟังก์ชันจำลองสำหรับฟังก์ชัน `getUserDataFromAPI` ที่นำเข้ามาจากโมดูล `./api` `mockResolvedValue` ถูกใช้เพื่อระบุค่าที่จะคืนกลับของ mock ส่วน `mockRestore` มีความสำคัญเพื่อให้แน่ใจว่าการทดสอบอื่น ๆ จะไม่ใช้เวอร์ชันที่ถูกจำลองโดยไม่ได้ตั้งใจ
Python กับ pytest และ unittest.mock
Python มีไลบรารีหลายตัวสำหรับการทำ mocking รวมถึง `unittest.mock` (ที่มีมาในตัว) และไลบรารีเช่น `pytest-mock` เพื่อการใช้งานที่ง่ายขึ้นกับ pytest
# ฟังก์ชันที่จะทดสอบ
def get_data_from_api(url):
# ในสถานการณ์จริง ส่วนนี้จะทำการเรียก API
# เพื่อความเรียบง่าย เราจะจำลองการเรียก API
if url == "https://example.com/api":
return {"data": "API data"}
else:
return None
def process_data(url):
data = get_data_from_api(url)
if data:
return data["data"]
else:
return "No data found"
# เคสทดสอบโดยใช้ unittest.mock
import unittest
from unittest.mock import patch
class TestProcessData(unittest.TestCase):
@patch('__main__.get_data_from_api') # แทนที่ get_data_from_api ในโมดูลหลัก
def test_process_data_success(self, mock_get_data_from_api):
# กำหนดค่า mock
mock_get_data_from_api.return_value = {"data": "Mocked data"}
# เรียกฟังก์ชันที่กำลังทดสอบ
result = process_data("https://example.com/api")
# ตรวจสอบผลลัพธ์
self.assertEqual(result, "Mocked data")
mock_get_data_from_api.assert_called_once_with("https://example.com/api")
@patch('__main__.get_data_from_api')
def test_process_data_failure(self, mock_get_data_from_api):
mock_get_data_from_api.return_value = None
result = process_data("https://example.com/api")
self.assertEqual(result, "No data found")
if __name__ == '__main__':
unittest.main()
ตัวอย่างนี้ใช้ `unittest.mock.patch` เพื่อแทนที่ฟังก์ชัน `get_data_from_api` ด้วย mock การทดสอบจะกำหนดค่า mock ให้คืนค่าที่ระบุ จากนั้นตรวจสอบว่าฟังก์ชัน `process_data` คืนผลลัพธ์ที่คาดหวัง
นี่คือตัวอย่างเดียวกันโดยใช้ `pytest-mock`:
# เวอร์ชัน pytest
import pytest
def get_data_from_api(url):
# ในสถานการณ์จริง ส่วนนี้จะทำการเรียก API
# เพื่อความเรียบง่าย เราจะจำลองการเรียก API
if url == "https://example.com/api":
return {"data": "API data"}
else:
return None
def process_data(url):
data = get_data_from_api(url)
if data:
return data["data"]
else:
return "No data found"
def test_process_data_success(mocker):
mocker.patch('__main__.get_data_from_api', return_value={"data": "Mocked data"})
result = process_data("https://example.com/api")
assert result == "Mocked data"
def test_process_data_failure(mocker):
mocker.patch('__main__.get_data_from_api', return_value=None)
result = process_data("https://example.com/api")
assert result == "No data found"
ไลบรารี `pytest-mock` มี `mocker` fixture ที่ช่วยให้การสร้างและกำหนดค่า mock ภายใน pytest tests ง่ายขึ้น
Java กับ Mockito
Mockito เป็นเฟรมเวิร์กการทำ mocking ที่ได้รับความนิยมสำหรับ Java
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
interface DataFetcher {
String fetchData(String url);
}
class DataProcessor {
private final DataFetcher dataFetcher;
public DataProcessor(DataFetcher dataFetcher) {
this.dataFetcher = dataFetcher;
}
public String processData(String url) {
String data = dataFetcher.fetchData(url);
if (data != null) {
return "Processed: " + data;
} else {
return "No data";
}
}
}
public class DataProcessorTest {
@Test
public void testProcessDataSuccess() {
// สร้าง mock DataFetcher
DataFetcher mockDataFetcher = mock(DataFetcher.class);
// กำหนดค่า mock
when(mockDataFetcher.fetchData("https://example.com/api")).thenReturn("API Data");
// สร้าง DataProcessor ด้วย mock
DataProcessor dataProcessor = new DataProcessor(mockDataFetcher);
// เรียกฟังก์ชันที่กำลังทดสอบ
String result = dataProcessor.processData("https://example.com/api");
// ตรวจสอบผลลัพธ์
assertEquals("Processed: API Data", result);
// ตรวจสอบว่า mock ถูกเรียกใช้งาน
verify(mockDataFetcher).fetchData("https://example.com/api");
}
@Test
public void testProcessDataFailure() {
DataFetcher mockDataFetcher = mock(DataFetcher.class);
when(mockDataFetcher.fetchData("https://example.com/api")).thenReturn(null);
DataProcessor dataProcessor = new DataProcessor(mockDataFetcher);
String result = dataProcessor.processData("https://example.com/api");
assertEquals("No data", result);
verify(mockDataFetcher).fetchData("https://example.com/api");
}
}
ในตัวอย่างนี้ `Mockito.mock()` จะสร้างอ็อบเจกต์จำลองสำหรับอินเทอร์เฟซ `DataFetcher` `when()` ถูกใช้เพื่อกำหนดค่าคืนกลับของ mock และ `verify()` ถูกใช้เพื่อตรวจสอบว่า mock ถูกเรียกด้วยอาร์กิวเมนต์ที่คาดหวัง
แนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้ฟังก์ชันจำลอง
- ใช้ Mock เท่าที่จำเป็น: จำลองเฉพาะการพึ่งพาที่เป็นส่วนประกอบภายนอกจริงๆ หรือที่เพิ่มความซับซ้อนอย่างมีนัยสำคัญ หลีกเลี่ยงการจำลองรายละเอียดการทำงานภายใน
- ทำให้ Mock เรียบง่าย: ฟังก์ชันจำลองควรจะเรียบง่ายที่สุดเท่าที่จะทำได้เพื่อหลีกเลี่ยงการนำบั๊กเข้ามาในการทดสอบของคุณ
- ใช้ Dependency Injection: ใช้ Dependency Injection เพื่อให้ง่ายต่อการแทนที่การพึ่งพาส่วนประกอบจริงด้วยอ็อบเจกต์จำลอง การใช้ Constructor Injection เป็นที่นิยมมากกว่าเพราะทำให้เห็นการพึ่งพาอย่างชัดเจน
- ตรวจสอบปฏิสัมพันธ์: ตรวจสอบเสมอว่าหน่วยที่กำลังทดสอบของคุณมีปฏิสัมพันธ์กับฟังก์ชันจำลองในแบบที่คาดหวัง
- คืนค่าฟังก์ชันดั้งเดิม: หลังจากการทดสอบแต่ละครั้ง ให้คืนค่าฟังก์ชันดั้งเดิมโดยการลบอ็อบเจกต์จำลองและกลับไปใช้การพึ่งพาส่วนประกอบจริง
- จัดทำเอกสารสำหรับ Mock: จัดทำเอกสารสำหรับฟังก์ชันจำลองของคุณอย่างชัดเจนเพื่ออธิบายวัตถุประสงค์และพฤติกรรมของมัน
- หลีกเลี่ยงการกำหนดเงื่อนไขที่เจาะจงเกินไป: อย่าตรวจสอบทุกปฏิสัมพันธ์ แต่ให้มุ่งเน้นไปที่ปฏิสัมพันธ์หลักที่จำเป็นต่อพฤติกรรมที่คุณกำลังทดสอบ
- พิจารณาการทดสอบแบบบูรณาการ (Integration Tests): แม้ว่า unit tests ที่มี mock จะมีความสำคัญ อย่าลืมเสริมด้วยการทดสอบแบบบูรณาการที่ตรวจสอบปฏิสัมพันธ์ระหว่างส่วนประกอบจริง
ทางเลือกอื่นนอกเหนือจากฟังก์ชันจำลอง
แม้ว่าฟังก์ชันจำลองจะเป็นเครื่องมือที่ทรงพลัง แต่ก็ไม่ได้เป็นทางออกที่ดีที่สุดเสมอไป ในบางกรณี เทคนิคอื่นอาจเหมาะสมกว่า:
- Stubs: Stubs จะเรียบง่ายกว่า Mocks โดยจะให้การตอบสนองที่กำหนดไว้ล่วงหน้าต่อการเรียกฟังก์ชัน แต่โดยทั่วไปแล้วจะไม่ตรวจสอบว่าการเรียกเหล่านั้นทำอย่างไร มีประโยชน์เมื่อคุณต้องการเพียงแค่ควบคุมข้อมูลนำเข้าของหน่วยที่กำลังทดสอบ
- Spies: Spies ช่วยให้คุณสามารถสังเกตพฤติกรรมของฟังก์ชันจริงในขณะที่ยังคงปล่อยให้มันทำงานตามตรรกะดั้งเดิมได้ มีประโยชน์เมื่อคุณต้องการตรวจสอบว่าฟังก์ชันถูกเรียกด้วยอาร์กิวเมนต์ที่ระบุหรือจำนวนครั้งที่กำหนด โดยไม่ต้องแทนที่ฟังก์ชันการทำงานของมันทั้งหมด
- Fakes: Fakes คือการสร้างส่วนประกอบที่พึ่งพาขึ้นมาใหม่ให้ทำงานได้จริง แต่เรียบง่ายกว่าเพื่อวัตถุประสงค์ในการทดสอบ ตัวอย่างเช่น ฐานข้อมูลในหน่วยความจำ (in-memory database)
- การทดสอบแบบบูรณาการ (Integration Tests): การทดสอบแบบบูรณาการจะตรวจสอบปฏิสัมพันธ์ระหว่างส่วนประกอบหลายๆ ส่วน อาจเป็นทางเลือกที่ดีแทน unit tests ที่มี mock เมื่อคุณต้องการทดสอบพฤติกรรมของระบบโดยรวม
สรุป
ฟังก์ชันจำลองเป็นเครื่องมือสำคัญสำหรับการเขียน unit tests ที่มีประสิทธิภาพ ช่วยให้คุณสามารถแยกส่วนประกอบ ควบคุมพฤติกรรม จำลองสภาวะข้อผิดพลาด และทดสอบโค้ดแบบอะซิงโครนัสได้ การปฏิบัติตามแนวทางที่ดีที่สุดและทำความเข้าใจทางเลือกอื่นๆ จะช่วยให้คุณสามารถใช้ประโยชน์จากฟังก์ชันจำลองเพื่อสร้างซอฟต์แวร์ที่แข็งแกร่ง เชื่อถือได้ และบำรุงรักษาง่ายขึ้น อย่าลืมพิจารณาข้อดีข้อเสียและเลือกเทคนิคการทดสอบที่เหมาะสมสำหรับแต่ละสถานการณ์เพื่อสร้างกลยุทธ์การทดสอบที่ครอบคลุมและมีประสิทธิภาพ ไม่ว่าคุณจะสร้างซอฟต์แวร์จากส่วนไหนของโลกก็ตาม