MSW在单个测试中第二次无法与更新的数据匹配相同的请求
我有一个简单的用RTK查询挂钩生成的房屋列表,其中可以标记为喜欢的项目,并根据标签无效自动进行数据倒置。当我在测试中运行项目时,一切都可以匹配MSW中的第二次匹配,在突变成功后通过标签无效触发了该请求。
服务:
export const homesApi = createApi({
reducerPath: 'homesApi',
baseQuery: fetchBaseQuery({
baseUrl: API_URL,
prepareHeaders: (headers, { getState }) => {
headers.set('Accept', `application/json`);
return headers;
},
}),
tagTypes: [
'Homes',
],
endpoints: (builder) => ({
getHomes: builder.query({
query: (params) => {
const url = qs.stringifyUrl(
{ url: '/homes', query: params },
{ skipEmptyString: true, skipNull: true }
);
return url
},
providesTags: (result) =>
result?.data
? [
...result.data.map(({ id }) => ({ type: 'Homes', id })),
{ type: 'Homes', id: 'LIST' },
]
: [{ type: 'Homes', id: 'LIST' }],
}),
homeFavorite: builder.mutation({
query(payload) {
const {id} = payload;
const url = `/homes/${id}/favorite`;
return {
url,
method: 'POST'
};
},
invalidatesTags: () => [{ type: 'Homes', id: 'LIST' }],
}),
}),
});
export const {
useGetHomesQuery,
useHomeFavoriteMutation
} = homesApi;
测试:
const store = configureStore({
reducer: {
[homesApi.reducerPath]: homesApi.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
immutableCheck: false,
}).concat(
homesApi.middleware
),
});
setupListeners(store.dispatch);
let cleanupListeners;
describe('Homes component', () => {
beforeEach(() => {
cleanupListeners = setupListeners(store.dispatch)
})
afterEach(() => {
cleanupListeners();
store.dispatch(homesApi.util.resetApiState())
});
it('should mark item favorite', async() => {
server.use(
rest.get(`${API_URL}/homes`, (req, res, ctx) => {
return res(
ctx.json(MOCK_SUCCESS)
);
}),
rest.post(`${API_URL}/homes/1/favorite`, (req, res, ctx) => {
return res(
ctx.json({})
);
}),
);
render(
<Provider store={store}>
<BrowserRouter>
<Routes>
<Route path={'/'} element={<Homes/>}/>
</Routes>
</BrowserRouter>
</Provider>
);
const user = userEvent.setup();
const items = await screen.findAllByTestId('homeItem');
expect(items.length).toBe(5);
const icon = within(items[0]).getByTestId('fIcon');
expect(icon).not.toHaveClass('fav');
await user.click(icon);
//here I try to match the request for the second time with new data
server.use(
rest.get(`${API_URL}/homes`, (req, res, ctx) => {
return res(
ctx.json(MOCK_SUCCESS_UPDATED)
);
}),
)
const itemsNew = await screen.findAllByTestId('homeItem');
expect(within(itemsNew[0]).getByTestId('fIcon')).toHaveClass('fav');
})
});
任何想法我在做什么错,因为无论我尝试什么,我都无法第二次匹配相同的获取请求。以下是我遇到的错误
[MSW]警告:捕获了无匹配请求处理程序的请求:
I have a simple list of homes generated with RTK query hooks where item can be marked favorite and data refetched automatically based on tags invalidation. While everything works when I run the project within the test msw is not able to match the same GET request called second time after mutation success triggers it via tags invalidation.
service:
export const homesApi = createApi({
reducerPath: 'homesApi',
baseQuery: fetchBaseQuery({
baseUrl: API_URL,
prepareHeaders: (headers, { getState }) => {
headers.set('Accept', `application/json`);
return headers;
},
}),
tagTypes: [
'Homes',
],
endpoints: (builder) => ({
getHomes: builder.query({
query: (params) => {
const url = qs.stringifyUrl(
{ url: '/homes', query: params },
{ skipEmptyString: true, skipNull: true }
);
return url
},
providesTags: (result) =>
result?.data
? [
...result.data.map(({ id }) => ({ type: 'Homes', id })),
{ type: 'Homes', id: 'LIST' },
]
: [{ type: 'Homes', id: 'LIST' }],
}),
homeFavorite: builder.mutation({
query(payload) {
const {id} = payload;
const url = `/homes/${id}/favorite`;
return {
url,
method: 'POST'
};
},
invalidatesTags: () => [{ type: 'Homes', id: 'LIST' }],
}),
}),
});
export const {
useGetHomesQuery,
useHomeFavoriteMutation
} = homesApi;
test:
const store = configureStore({
reducer: {
[homesApi.reducerPath]: homesApi.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
immutableCheck: false,
}).concat(
homesApi.middleware
),
});
setupListeners(store.dispatch);
let cleanupListeners;
describe('Homes component', () => {
beforeEach(() => {
cleanupListeners = setupListeners(store.dispatch)
})
afterEach(() => {
cleanupListeners();
store.dispatch(homesApi.util.resetApiState())
});
it('should mark item favorite', async() => {
server.use(
rest.get(`${API_URL}/homes`, (req, res, ctx) => {
return res(
ctx.json(MOCK_SUCCESS)
);
}),
rest.post(`${API_URL}/homes/1/favorite`, (req, res, ctx) => {
return res(
ctx.json({})
);
}),
);
render(
<Provider store={store}>
<BrowserRouter>
<Routes>
<Route path={'/'} element={<Homes/>}/>
</Routes>
</BrowserRouter>
</Provider>
);
const user = userEvent.setup();
const items = await screen.findAllByTestId('homeItem');
expect(items.length).toBe(5);
const icon = within(items[0]).getByTestId('fIcon');
expect(icon).not.toHaveClass('fav');
await user.click(icon);
//here I try to match the request for the second time with new data
server.use(
rest.get(`${API_URL}/homes`, (req, res, ctx) => {
return res(
ctx.json(MOCK_SUCCESS_UPDATED)
);
}),
)
const itemsNew = await screen.findAllByTestId('homeItem');
expect(within(itemsNew[0]).getByTestId('fIcon')).toHaveClass('fav');
})
});
any idea what am I doing wrong since I am not able to match the same GET request for the second time no matter what I try. below is the error I am getting
[MSW] Warning: captured a request without a matching request handler:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
尝试使用
https://mswjs.io/docs/docs/api/api/response/once/once/once
基本思想是res.once模拟响应,完全是1个API调用
,如果您两次调用相同的端点,它只会响应一次
是我的用例删除数据,以便在UI中存在更新的数据,
请尝试使用全局处理程序,并且在您的测试中进行:
当然,两次,上面的代码在同一测试子句中
try out with
https://mswjs.io/docs/api/response/once
basic idea that res.once mock response for exactly 1 api call
if you call the same endpoint twice, it will only respond once
here is my use case, I fetch data, i then run a post request to add data, then i need to refetch the data so that the updated data is present in UI,
try with no global handler, and in your test, do:
twice, of course, above codes were in the same test clause