Logo

dev-resources.site

for different kinds of informations.

การเขียนเทสเพื่อทดสอบโปรเจคแบบ React + Firebase

Published at
11/16/2024
Categories
react
firebase
test
Author
Weerayut Teja
Categories
3 categories in total
react
open
firebase
open
test
open
การเขียนเทสเพื่อทดสอบโปรเจคแบบ React + Firebase

การเขียนเทสต์สำหรับโปรเจคที่ใช้ Firebase + React มีความสำคัญในการตรวจสอบความถูกต้องของฟังก์ชันต่าง ๆ โดยเฉพาะเมื่อ Firebase ให้บริการทั้งในส่วนของ Backend และ API การเทสต์จึงต้องครอบคลุมทั้งการทำงานของ React Component และการเชื่อมต่อกับ Firebase โดยมีแนวทางดังนี้ :

ประเภทของการเทสต์ที่ควรมีในโปรเจค

  1. Unit Test
    • ทดสอบฟังก์ชันหรือโมดูลที่แยกออกมา เช่น การเรียก Firebase API
  2. Integration Test
    • ทดสอบการทำงานระหว่าง Component React และ Firebase รวมถึงการทำงานร่วมกันระหว่างโมดูล
  3. 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, "[email protected]", "password123");

    expect(signInWithEmailAndPassword).toHaveBeenCalledWith(mockAuth, "[email protected]", "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: "[email protected]" };
    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
  1. ติดตั้ง Firebase CLI:
npm install -g firebase-tools
  1. เปิด Emulator:
firebase emulators:start
  1. กำหนดค่าให้ 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("[email protected]");
        cy.get("input[name=password]").type("password123");
        cy.get("button[type=submit]").click();
        cy.url().should("include", "/dashboard");
        cy.contains("Welcome, [email protected]").should("be.visible");
    });
});

สรุป

  1. แยกฟังก์ชัน Firebase ออกมาใน Utility หรือ Hook เพื่อให้ Mock และเทสต์ได้ง่าย
  2. ใช้ Mocking Library เช่น Jest เพื่อจำลอง Firebase SDK
  3. ตั้งค่า Firebase Emulator สำหรับการทดสอบในสภาพแวดล้อมที่ใกล้เคียงของจริง
  4. ใช้ E2E Test สำหรับกระบวนการที่เกี่ยวข้องกับผู้ใช้จริง เช่น การล็อกอินและดึงข้อมูล

ด้วยแนวทางนี้ คุณสามารถเขียนเทสต์ได้ทั้งในระดับ Unit, Integration, และ E2E ช่วยให้โปรเจคมีความเสถียรและลดโอกาสเกิดข้อผิดพลาดในอนาคต

Featured ones: