我应该在这个包装 useSWR 的自定义挂钩中测试什么?
What should i test in this custom hook that is wrapping useSWR?
我创建了一个名为 useCity 的自定义挂钩。它正在包装使用 useSWR 进行的 API 调用。
这里是钩子的代码:
import useSWR from 'swr';
import { City } from '../interfaces';
import { BASE_URL } from '../../config';
interface CitiesResponse {
data?: {
records: {
fields: {
city: string;
accentcity: string;
}
}[]
},
error?: {
message: string;
}
};
interface Props {
start?: number;
rows: number;
query?: string;
sort?: 'population';
exclude?: string[];
}
const useCity = ({ start = 0, rows, query, sort, exclude }: Props) => {
const params = [`start=${start}`, `rows=${rows}`];
if (query) params.push(`q=${query}`);
if (sort) params.push(`sort=${sort}`);
if (exclude && exclude.length > 0) params.push(...exclude.map(city => `exclude.city=${city}`))
const { data, error }: CitiesResponse = useSWR(
`${BASE_URL.CITIES_SERVICE}?dataset=worldcitiespop&facet=city&${params.join('&')}`,
{ revalidateOnFocus: false, }
);
const cities: City[] = data?.records.map(record => ({
name: record.fields.city,
title: record.fields.accentcity,
})) || [];
return {
cities,
loading: !error && !data,
error,
};
};
export default useCity;
现在,我需要测试挂钩。所以,我尝试使用 msw
和 @testing-library/react-hooks
.
这是我的尝试:
const server = setupServer(
rest.get(BASE_URL.CITIES_SERVICE, (req, res, ctx) => {
const start = req.url.searchParams.get('start');
const rows = req.url.searchParams.get('rows');
const query = req.url.searchParams.get('query');
const sort = req.url.searchParams.get('sort');
const exclude = req.url.searchParams.getAll('exclude.city');
const getReturnVal: () => DatabaseCity[] = () => {
// i will write some code that assumes what server will return
};
return res(
ctx.status(200),
ctx.json({
records: getReturnVal(),
}),
);
}),
...fallbackHandlers,
);
beforeAll(() => server.listen());
afterEach(() => {
server.resetHandlers();
cache.clear();
});
afterAll(() => server.close());
it('should return number of cities equal to passed in rows', async () => {
const wrapper = ({ children } : { children: ReactNode }) => (
<SWRConfig value={{ dedupingInterval: 0 }}>
{children}
</SWRConfig>
);
const { result, waitForNextUpdate, } = renderHook(() => useCity({ rows: 2 }), { wrapper });
const { cities:_cities, loading:_loading, error:_error } = result.current;
expect(_cities).toHaveLength(0);
await waitForNextUpdate();
const { cities, loading, error } = result.current;
expect(cities).toHaveLength(2);
});
我认为一旦我实现了模拟功能,测试用例就会通过。
但我不知道这是否是测试这种钩子的正确方法。我是前端开发人员,我有责任测试 API 调用吗?
我不熟悉编写涉及 API 调用的测试用例。我正朝着正确的方向前进吗?我不知道这种测试叫什么。如果有人能告诉我我正在执行的测试类型,那么它将帮助我 google 寻找解决方案,而不是浪费其他开发人员的时间来回答我的问题。
看来您的方向是正确的。
你的 useCity
钩子基本上做了两件你可以在测试中验证的事情:
- 建立一个url
- 将城市转换为另一种格式
您可以通过使用间谍来验证 useSWR
是用正确的 url 调用的:
import * as SWR from 'swr';
jest.spyOn(SWR, 'default'); // write this line before rendering the hook.
expect(SWR.default).toHaveBeenCalledWith(expectedUrl, {}); // pass any options that were passed in actual object
您可以通过
验证useCities
returns正确的城市
const { cities } = result.current;
expect(cities).toEqual(expectedCities);
I am a frontend developer, is this my responsibility to test that API call?
我认为这取决于您找到答案。我个人认为我有责任测试我编写的任何代码——这当然不是教条并且是上下文敏感的。
I don't know what this kind of tests are called. If someone can tell me the kind of the test I am perfoming, then it will help me google for the solutions
对此可能没有明确的答案。有些人会称之为单元测试(因为 useCities
是一个“单元”)。其他人可能称之为集成测试(因为您在“集成”中测试 useCities
和 useSWR
)。
你最好的选择是google诸如“如何测试反应挂钩”或“如何测试反应组件”之类的东西。 RTL 文档是一个很好的起点。
附加说明
我个人几乎从不单独测试 hooks。我发现为使用挂钩的组件编写集成测试更容易、更直观。
但是,如果您的钩子将被其他项目使用,我认为单独测试它们是有意义的,就像您在这里所做的那样。
我创建了一个名为 useCity 的自定义挂钩。它正在包装使用 useSWR 进行的 API 调用。
这里是钩子的代码:
import useSWR from 'swr';
import { City } from '../interfaces';
import { BASE_URL } from '../../config';
interface CitiesResponse {
data?: {
records: {
fields: {
city: string;
accentcity: string;
}
}[]
},
error?: {
message: string;
}
};
interface Props {
start?: number;
rows: number;
query?: string;
sort?: 'population';
exclude?: string[];
}
const useCity = ({ start = 0, rows, query, sort, exclude }: Props) => {
const params = [`start=${start}`, `rows=${rows}`];
if (query) params.push(`q=${query}`);
if (sort) params.push(`sort=${sort}`);
if (exclude && exclude.length > 0) params.push(...exclude.map(city => `exclude.city=${city}`))
const { data, error }: CitiesResponse = useSWR(
`${BASE_URL.CITIES_SERVICE}?dataset=worldcitiespop&facet=city&${params.join('&')}`,
{ revalidateOnFocus: false, }
);
const cities: City[] = data?.records.map(record => ({
name: record.fields.city,
title: record.fields.accentcity,
})) || [];
return {
cities,
loading: !error && !data,
error,
};
};
export default useCity;
现在,我需要测试挂钩。所以,我尝试使用 msw
和 @testing-library/react-hooks
.
这是我的尝试:
const server = setupServer(
rest.get(BASE_URL.CITIES_SERVICE, (req, res, ctx) => {
const start = req.url.searchParams.get('start');
const rows = req.url.searchParams.get('rows');
const query = req.url.searchParams.get('query');
const sort = req.url.searchParams.get('sort');
const exclude = req.url.searchParams.getAll('exclude.city');
const getReturnVal: () => DatabaseCity[] = () => {
// i will write some code that assumes what server will return
};
return res(
ctx.status(200),
ctx.json({
records: getReturnVal(),
}),
);
}),
...fallbackHandlers,
);
beforeAll(() => server.listen());
afterEach(() => {
server.resetHandlers();
cache.clear();
});
afterAll(() => server.close());
it('should return number of cities equal to passed in rows', async () => {
const wrapper = ({ children } : { children: ReactNode }) => (
<SWRConfig value={{ dedupingInterval: 0 }}>
{children}
</SWRConfig>
);
const { result, waitForNextUpdate, } = renderHook(() => useCity({ rows: 2 }), { wrapper });
const { cities:_cities, loading:_loading, error:_error } = result.current;
expect(_cities).toHaveLength(0);
await waitForNextUpdate();
const { cities, loading, error } = result.current;
expect(cities).toHaveLength(2);
});
我认为一旦我实现了模拟功能,测试用例就会通过。
但我不知道这是否是测试这种钩子的正确方法。我是前端开发人员,我有责任测试 API 调用吗?
我不熟悉编写涉及 API 调用的测试用例。我正朝着正确的方向前进吗?我不知道这种测试叫什么。如果有人能告诉我我正在执行的测试类型,那么它将帮助我 google 寻找解决方案,而不是浪费其他开发人员的时间来回答我的问题。
看来您的方向是正确的。
你的 useCity
钩子基本上做了两件你可以在测试中验证的事情:
- 建立一个url
- 将城市转换为另一种格式
您可以通过使用间谍来验证 useSWR
是用正确的 url 调用的:
import * as SWR from 'swr';
jest.spyOn(SWR, 'default'); // write this line before rendering the hook.
expect(SWR.default).toHaveBeenCalledWith(expectedUrl, {}); // pass any options that were passed in actual object
您可以通过
验证useCities
returns正确的城市
const { cities } = result.current;
expect(cities).toEqual(expectedCities);
I am a frontend developer, is this my responsibility to test that API call?
我认为这取决于您找到答案。我个人认为我有责任测试我编写的任何代码——这当然不是教条并且是上下文敏感的。
I don't know what this kind of tests are called. If someone can tell me the kind of the test I am perfoming, then it will help me google for the solutions
对此可能没有明确的答案。有些人会称之为单元测试(因为 useCities
是一个“单元”)。其他人可能称之为集成测试(因为您在“集成”中测试 useCities
和 useSWR
)。
你最好的选择是google诸如“如何测试反应挂钩”或“如何测试反应组件”之类的东西。 RTL 文档是一个很好的起点。
附加说明
我个人几乎从不单独测试 hooks。我发现为使用挂钩的组件编写集成测试更容易、更直观。
但是,如果您的钩子将被其他项目使用,我认为单独测试它们是有意义的,就像您在这里所做的那样。