describe("Board Row Component Test", () => {
  beforeEach(() => {
    render(
      <BoardRow
        title={mockRowData.title}
        content={mockRowData.content}
        userId={mockRowData.userId}
        postId={mockRowData.postId}
        upload={mockRowData.upload}
        count={mockRowData.count}
      />
    );
  });
  
...
test("게시글 행을 클릭하면 해당 게시글의 상세 페이지로 이동한다.", () => {
    const push = jest.fn();
    // useRouter의 타입을 올바르게 설정하여 모킹
    (useRouter as jest.Mock).mockImplementation(() => ({
      push,
    }));
    const row = screen.getByTestId("row");
    fireEvent.click(row);
    expect(push).toHaveBeenCalledWith(`/post/${mockRowData.postId}`);
  });
});
게시글 행을 클릭하면 해당 게시글의 상세 페이지로 이동한다. 라는 테스트는 useRouter를 사용한 동작을 테스트하기 때문에 useRouter에 대한 Mocking과 Push 동작에 대한 mocking이 필요하다.
위 코드에서 해당 테스트에서만 useRouter를 사용하기 때문에 테스트 케이스 내부에서 useRouter를 mocking해준 후 테스트를 돌렸을 때 위의 에러를 마주쳤다.
문제는 useRouter와 render함수의 우선순위 관계라고 생각했다.
랜더링 로직과 Mocking 우선순위를 따져보면, beforeEach 내부에 컴포넌트가 랜더링 된 이후에 useRouter를 mocking 한다. 이미 랜더링 된 상태에서 useRouter의 동작을 mocking 함수로 설정하고 있기 때문에 원하는 방식으로 테스트가 진행되고 있지 않았던 것 같다.
그래서 아래와 같이 mocking 함수의 위치를 옮겨주거나, 컴포넌트를 다시 랜더링하는 방식을 사용하면 해결할 수 있다.
test("게시글 행을 클릭하면 해당 게시글의 상세 페이지로 이동한다.", () => {
    const push = jest.fn();
    // useRouter의 타입을 올바르게 설정하여 모킹
    (useRouter as jest.Mock).mockImplementation(() => ({
      push,
    }));
		
		// 다시 컴포넌트를 랜더링 한다.
    render(
      <BoardRow
        title={mockRowData.title}
        content={mockRowData.content}
        userId={mockRowData.userId}
        postId={mockRowData.postId}
        upload={mockRowData.upload}
        count={mockRowData.count}
      />
    );
    const row = screen.getByTestId("row");
    fireEvent.click(row);
    expect(push).toHaveBeenCalledWith(`/post/${mockRowData.postId}`);
  });
describe("Header Test", () => {
  beforeEach(() => {
    render(
      <UserInfoStoreContext.Provider value={mockStore}>
        <Header />
      </UserInfoStoreContext.Provider>
    );
});
      
  test("초기 랜더링 - 로그인이 되어있지 않은 경우 '로그인이 필요합니다.'문구가 보인다.", async () => {
    let userIdElement = screen.getByTestId("header-info");
    // Mocking 상태를 로그아웃 상태로 변경
    await act(async () => {
      mockStore.setState({ id: "" });
        });
    
    render(
      <UserInfoStoreContext.Provider value={mockStore}>
        <Header />
      </UserInfoStoreContext.Provider>
    );
    
    screen.getByTestId("header-info");
    
        expect(userIdElement).toHaveTextContent("로그인이 필요합니다.");
      });
    });
→ 하지만 로그아웃, 로그인 버튼이 둘다 보인다는 테스트 결과를 받게 되었음.
  → 기존 beforeEach()로 요소를 랜더링하는 방식은 rerender 함수를 전달 받을 수 없기 때문에 파일 상단에서 wrapper 함수로 감싼후 해당 함수를 재사용할 수 있도록 수정해주었다.
  const renderHeader = () => {
  return render(
    <UserInfoStoreContext.Provider value={mockStore}>
      <Header />
    </UserInfoStoreContext.Provider>
  );
};
test("초기 랜더링 - 로그인이 되어있지 않은 경우 '로그인이 필요합니다.'문구가 보인다.", async () => {
  const { rerender } = renderHeader();
  let userIdElement = screen.getByTestId("header-info");
  // Mocking 상태를 로그아웃 상태로 변경
  await act(async () => {
    mockStore.setState({ id: "" });
  });
  rerender(
    <UserInfoStoreContext.Provider value={mockStore}>
      <Header />
    </UserInfoStoreContext.Provider>
  );
  screen.getByTestId("header-info");
  expect(userIdElement).toHaveTextContent("로그인이 필요합니다.");
});  위 코드처럼 수정했을 때 비로소 테스트를 통과할 수 있었다