กลับไปหน้าหลัก

บทที่ 13: Testing

Unit Test
Integration
E2E
Best Practice

🧪 Unit Test

Unit Testing คือการทดสอบฟังก์ชันหรือส่วนย่อยของโค้ดแต่ละตัวแยกกัน

1. Basic Jest Matchers
// ตัวอย่าง Jest Matchers ที่ใช้บ่อย
describe('Basic Jest Matchers', () => {
  test('equality matchers', () => {
    expect(2 + 2).toBe(4);                    // ตรวจสอบค่าเท่ากัน
    expect({ name: 'John' }).toEqual({ name: 'John' }); // ตรวจสอบ object
  });

  test('truthiness matchers', () => {
    expect(true).toBeTruthy();                // ค่าที่เป็น true
    expect(false).toBeFalsy();                // ค่าที่เป็น false
    expect('hello').toBeTruthy();             // string ไม่ว่าง = truthy
    expect('').toBeFalsy();                   // string ว่าง = falsy
    expect(null).toBeNull();                  // ตรวจสอบ null
    expect(undefined).toBeUndefined();        // ตรวจสอบ undefined
  });

  test('number matchers', () => {
    expect(2 + 2).toBeGreaterThan(3);         // มากกว่า
    expect(2 + 2).toBeGreaterThanOrEqual(4);  // มากกว่าหรือเท่ากับ
    expect(2 + 2).toBeLessThan(5);            // น้อยกว่า
    expect(0.1 + 0.2).toBeCloseTo(0.3);       // ใกล้เคียง (สำหรับ float)
  });

  test('string matchers', () => {
    expect('hello world').toMatch(/world/);    // ตรงกับ regex
    expect('hello world').toContain('hello');  // มีคำนี้อยู่
  });

  test('array matchers', () => {
    expect(['apple', 'banana', 'orange']).toContain('banana');
    expect(['apple', 'banana']).toHaveLength(2);
  });

  test('exception matchers', () => {
    const throwError = () => {
      throw new Error('Something went wrong');
    };
    expect(throwError).toThrow();
    expect(throwError).toThrow('Something went wrong');
  });
});
2. Testing Functions with Side Effects
// utils/storage.js - ฟังก์ชันที่มี side effects
export function saveToLocalStorage(key, value) {
  try {
    localStorage.setItem(key, JSON.stringify(value));
    return true;
  } catch (error) {
    return false;
  }
}

export function getFromLocalStorage(key) {
  try {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : null;
  } catch (error) {
    return null;
  }
}

// __tests__/storage.test.js
import { saveToLocalStorage, getFromLocalStorage } from '../utils/storage';

// Mock localStorage เพราะ Jest ไม่มี localStorage
const localStorageMock = {
  getItem: jest.fn(),
  setItem: jest.fn(),
  removeItem: jest.fn(),
  clear: jest.fn(),
};
global.localStorage = localStorageMock;

describe('Local Storage Utils', () => {
  beforeEach(() => {
    // ล้าง mock ก่อนแต่ละ test
    jest.clearAllMocks();
  });

  test('should save data to localStorage', () => {
    const testData = { name: 'John', age: 30 };
    
    const result = saveToLocalStorage('user', testData);
    
    expect(result).toBe(true);
    expect(localStorage.setItem).toHaveBeenCalledWith(
      'user', 
      JSON.stringify(testData)
    );
  });

  test('should retrieve data from localStorage', () => {
    const testData = { name: 'John', age: 30 };
    localStorage.getItem.mockReturnValue(JSON.stringify(testData));
    
    const result = getFromLocalStorage('user');
    
    expect(result).toEqual(testData);
    expect(localStorage.getItem).toHaveBeenCalledWith('user');
  });

  test('should handle localStorage errors', () => {
    localStorage.setItem.mockImplementation(() => {
      throw new Error('Storage full');
    });
    
    const result = saveToLocalStorage('user', { name: 'John' });
    
    expect(result).toBe(false);
  });
});