我們主要就測兩個功能:
- initial render有正確呼叫useEffect call api
- intersection 有讓PostId增加一
一開始,一樣先做假的intersection替代global環境真實的Intersection
為了測試方便,我有回傳出了postId
剩下的就跟以前一樣,用mock做假資料,使用renderHook, act, waitFor這三個最主要的方法去做測試
const mockCallbacks: IntersectionObserverCallback[] = []; class MockIntersectionObserver implements IntersectionObserver { readonly root: Element | null = null; readonly rootMargin: string = ""; readonly thresholds: ReadonlyArray<number> = []; constructor(callback: IntersectionObserverCallback) { mockCallbacks.push(callback); } observe(target: Element): void {} unobserve(target: Element): void {} disconnect(): void {} takeRecords(): IntersectionObserverEntry[] { return []; } } (global as any).IntersectionObserver = MockIntersectionObserver;
return { loading, comments, intersectioningRef, postId };
import { renderHook, act, waitFor } from "@testing-library/react"; import MockAdapter from "axios-mock-adapter"; import axios from "axios"; import useGetComments from "./useGetComments"; const mockCallbacks: IntersectionObserverCallback[] = []; class MockIntersectionObserver implements IntersectionObserver { readonly root: Element | null = null; readonly rootMargin: string = ""; readonly thresholds: ReadonlyArray<number> = []; constructor(callback: IntersectionObserverCallback) { mockCallbacks.push(callback); } observe(target: Element): void {} unobserve(target: Element): void {} disconnect(): void {} takeRecords(): IntersectionObserverEntry[] { return []; } } (global as any).IntersectionObserver = MockIntersectionObserver; // This sets up the mock adapter on the default instance const mock = new MockAdapter(axios); describe("useGetComments", () => { afterEach(() => { mock.reset(); }); it("should fetch comments on initial render", async () => { const { result } = renderHook(() => useGetComments()); const mockData = [ { postId: 1, id: 1, name: "Comment 1", email: "test1@example.com", body: "Body 1", }, // ... other mock comments ]; mock .onGet("https://jsonplaceholder.typicode.com/comments?postId=1") .reply(200, mockData); expect(result.current.loading).toBe(true); waitFor(() => { expect(result.current.comments).toEqual(mockData); expect(result.current.loading).toBe(false); }); }); it("should increment postId when an element intersects", async () => { const { result } = renderHook(() => useGetComments()); // 使用 act 來模擬交互事件 act(() => { if (mockCallbacks.length > 0) { mockCallbacks[0]( [{ isIntersecting: true } as IntersectionObserverEntry], {} as IntersectionObserver ); } }); waitFor(() => { expect(result.current.postId).toBe(2); }); }); });