我想在第一次渲染组件时使用 react-testing-library 进行单元测试,从 API 获取一些信息。
所以我正在使用 setupServer 来模拟 API 并使用 REST 发送虚拟数据,但是组件中只有加载程序,并且 setupServer 无法正常工作
我该如何解决这个问题?
detail.tsx
import React, { FC, useEffect, useState } from 'react';
import { RouteComponentProps, useHistory, withRouter } from 'react-router-dom';
import {
actorInfo,
detailMovie,
movieInfo,
popularResponseType,
} from '../../types';
import { fetcher, } from '../../utils/request';
import * as S from './styles';
import * as C from '../../utils/constants';
import Loader from '../Loader';
interface movieID {
id: string;
}
const Detail: FC<RouteComponentProps<movieID>> = ({ match }) => {
const [detail, setDetail] = useState<detailMovie>();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(false);
useEffect(() => {
const getData = async () => {
setIsLoading(true);
const movieDetail: detailMovie = await fetcher(`https://api.themoviedb.org/3/movie/343611{API_KEY}&language=kr-KR`);
setDetail(movieDetail);
setIsLoading(false);
};
getData();
}, []);
if (error) {
return <p>something went wrong</p>;
}
return ( isLoading ? (
<Loader />
)
<S.Container>
<S.IntroduceContainer>
{detail ? (
<S.Poster src={`${C.IMAGE_URL_W500}/${detail?.poster_path}`} />
) : (
<S.Poster />
)}
<S.InfoContainer>
<S.Title>{detail?.title}</S.Title>
<S.RunningTime>{`${detail?.runtime}분`}</S.RunningTime>
<S.Description>{detail?.overview}</S.Description>
</S.InfoContainer>
</S.IntroduceContainer>
</S.Container>
);
};
export default withRouter(Detail);
detail.test.js
import React from 'react';
import { render, waitFor, screen } from '@testing-library/react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';
import Detail from '../index';
import movieDetailDummy from '../../../dummy/movieDummy';
import { Route, MemoryRouter } from 'react-router-dom';
import { act } from 'react-dom/test-utils';
import { API_KEY, API_URL_MOVIE } from '../../../utils/constants';
const server = setupServer(
rest.get(`https://api.themoviedb.org/3/movie/343611{API_KEY}&language=kr-KR`, (req, res, ctx) => {
return res(ctx.status(200), ctx.json(movieDetailDummy));
})
);
beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
const renderComponenet = ({ movieID }) =>
render(
<MemoryRouter initialEntries={[`/detail/${movieID}`]}>
<Route path="/detail/:id">
<Detail />
</Route>
</MemoryRouter>
);
describe('<Detail />', () => {
it('get movieDetail from tmdb', async () => {
act(() => {
renderComponent({ movieID: 343611 });
});
await waitFor(() => screen.getByText('잭 리처: 네버 고 백'));
});
});
fetcher
export const fetcher = async (url: string) => {
const response = await fetch(url);
if (!response.ok) {
const error = new Error('Error while fetching the data');
error.message = await response.json();
throw error;
}
const result = await response.json();
return result;
};