การเขียนเทสต์สำหรับโปรเจคที่ใช้ Firebase + React มีความสำคัญในการตรวจสอบความถูกต้องของฟังก์ชันต่าง ๆ โดยเฉพาะเมื่อ Firebase ให้บริการทั้งในส่วนของ Backend และ API การเทสต์จึงต้องครอบคลุมทั้งการทำงานของ React Component และการเชื่อมต่อกับ Firebase โดยมีแนวทางดังนี้ :
ประเภทของการเทสต์ที่ควรมีในโปรเจค
- Unit Test
- ทดสอบฟังก์ชันหรือโมดูลที่แยกออกมา เช่น การเรียก Firebase API
- Integration Test
- ทดสอบการทำงานระหว่าง Component React และ Firebase รวมถึงการทำงานร่วมกันระหว่างโมดูล
- End-to-End (E2E) Test
- ทดสอบกระบวนการใช้งานของผู้ใช้ เช่น การล็อกอิน การเพิ่มข้อมูลลง Firestore หรือการแสดงผลข้อมูลในหน้าเว็บ
การเขียนเทสต์ Firebase ใน React
1. การเทสต์ฟังก์ชันที่ใช้ Firebase API
Firebase มี Client SDK ที่ให้เราใช้เชื่อมต่อกับบริการต่าง ๆ เช่น Authentication, Firestore หรือ Realtime Database ในการเขียนเทสต์ คุณสามารถ Mock พฤติกรรมของ Firebase SDK ได้
ตัวอย่างการ Mock Firebase
- ใช้ไลบรารีอย่าง
jest.mock
เพื่อ Mock Firebase SDK
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";
jest.mock("firebase/auth", () => ({
getAuth: jest.fn(),
signInWithEmailAndPassword: jest.fn(),
}));
test("should call signInWithEmailAndPassword with correct arguments", async () => {
const mockAuth = {};
getAuth.mockReturnValue(mockAuth);
signInWithEmailAndPassword.mockResolvedValue({ user: { uid: "12345" } });
const result = await signInWithEmailAndPassword(mockAuth, "test@example.com", "password123");
expect(signInWithEmailAndPassword).toHaveBeenCalledWith(mockAuth, "test@example.com", "password123");
expect(result.user.uid).toBe("12345");
});
การ Mock SDK จะช่วยให้คุณหลีกเลี่ยงการเชื่อมต่อกับ Firebase จริงในขณะเทสต์
2. การเทสต์ React Component ที่เชื่อม Firebase
- React Component ที่เรียก Firebase API ควรแยกฟังก์ชัน Firebase ออกมาใน Utility หรือ Hook เพื่อให้ง่ายต่อการเทสต์
ตัวอย่าง Component และ Hook
// hooks/useFirebaseAuth.js
import { getAuth, onAuthStateChanged } from "firebase/auth";
import { useState, useEffect } from "react";
export function useFirebaseAuth() {
const [user, setUser] = useState(null);
useEffect(() => {
const auth = getAuth();
const unsubscribe = onAuthStateChanged(auth, setUser);
return unsubscribe;
}, []);
return user;
}
เทสต์ Hook ด้วย react-hooks-testing-library
import { renderHook } from "@testing-library/react";
import { useFirebaseAuth } from "./useFirebaseAuth";
import { getAuth, onAuthStateChanged } from "firebase/auth";
jest.mock("firebase/auth", () => ({
getAuth: jest.fn(),
onAuthStateChanged: jest.fn(),
}));
test("should set user when onAuthStateChanged is triggered", () => {
const mockUser = { uid: "12345", email: "test@example.com" };
onAuthStateChanged.mockImplementation((auth, callback) => {
callback(mockUser);
return jest.fn(); // Mock unsubscribe function
});
const { result } = renderHook(() => useFirebaseAuth());
expect(result.current).toEqual(mockUser);
});
3. การเขียน Integration Test
Integration Test จะทดสอบการทำงานระหว่าง React Component และ Firebase เช่น การแสดงผลข้อมูลจาก Firestore
ตัวอย่างการทดสอบ Firestore ด้วย Mock
import { render, screen } from "@testing-library/react";
import { collection, getDocs } from "firebase/firestore";
import MyComponent from "./MyComponent";
jest.mock("firebase/firestore", () => ({
collection: jest.fn(),
getDocs: jest.fn(),
}));
test("should display data from Firestore", async () => {
const mockData = [{ id: "1", data: () => ({ name: "Item 1" }) }];
getDocs.mockResolvedValue(mockData);
render(<MyComponent />);
const item = await screen.findByText("Item 1");
expect(item).toBeInTheDocument();
});
- คุณสามารถ Mock การตอบกลับของ Firestore เพื่อให้เทสต์สามารถจำลองข้อมูลได้
4. การเขียน End-to-End Test
- ใช้เครื่องมืออย่าง Cypress หรือ Playwright สำหรับการเทสต์ E2E
- การตั้งค่า Firebase Emulator จะช่วยให้สามารถทดสอบการทำงานร่วมกับ Firebase ได้โดยไม่ต้องเชื่อมต่อกับโปรเจคจริง
การตั้งค่า Firebase Emulator
- ติดตั้ง Firebase CLI:
npm install -g firebase-tools
- เปิด Emulator:
firebase emulators:start
- กำหนดค่าให้ React ใช้ Emulator:
import { connectAuthEmulator } from "firebase/auth";
import { connectFirestoreEmulator } from "firebase/firestore";
const auth = getAuth();
connectAuthEmulator(auth, "http://localhost:9099");
const firestore = getFirestore();
connectFirestoreEmulator(firestore, "localhost", 8080);
ตัวอย่าง Cypress Test
describe("Authentication Flow", () => {
it("should log in and display user dashboard", () => {
cy.visit("/login");
cy.get("input[name=email]").type("test@example.com");
cy.get("input[name=password]").type("password123");
cy.get("button[type=submit]").click();
cy.url().should("include", "/dashboard");
cy.contains("Welcome, test@example.com").should("be.visible");
});
});
สรุป
- แยกฟังก์ชัน Firebase ออกมาใน Utility หรือ Hook เพื่อให้ Mock และเทสต์ได้ง่าย
- ใช้ Mocking Library เช่น Jest เพื่อจำลอง Firebase SDK
- ตั้งค่า Firebase Emulator สำหรับการทดสอบในสภาพแวดล้อมที่ใกล้เคียงของจริง
- ใช้ E2E Test สำหรับกระบวนการที่เกี่ยวข้องกับผู้ใช้จริง เช่น การล็อกอินและดึงข้อมูล
ด้วยแนวทางนี้ คุณสามารถเขียนเทสต์ได้ทั้งในระดับ Unit, Integration, และ E2E ช่วยให้โปรเจคมีความเสถียรและลดโอกาสเกิดข้อผิดพลาดในอนาคต
Top comments (0)