msw 无法在单次测试中第二次将相同的请求与更新的数据相匹配

use*_*287 5 reactjs jestjs react-testing-library msw rtk-query

我有一个使用 RTK 查询挂钩生成的简单家庭列表,其中可以将项目标记为最喜欢的,并根据标签失效自动重新获取数据。虽然当我在测试中运行项目时一切正常,但 msw 无法匹配在突变成功通过标签失效触发后第二次调用的相同 GET 请求。

服务:

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;
Run Code Online (Sandbox Code Playgroud)

测试:

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');
      
    })
});
Run Code Online (Sandbox Code Playgroud)

不知道我做错了什么,因为无论我尝试什么,我都无法第二次匹配相同的 GET 请求。下面是我收到的错误

[MSW] 警告:捕获了没有匹配请求处理程序的请求:

小智 0

尝试一下

https://mswjs.io/docs/api/response/once

res.once 模拟响应恰好 1 个 api 调用的基本思想

如果你调用同一个端点两次,它只会响应一次

这是我的用例,我获取数据,然后运行发布请求来添加数据,然后我需要重新获取数据,以便更新的数据出现在 UI 中,

尝试不使用全局处理程序,并在测试中执行以下操作:

server.use(
  rest.get('your/endpoint', (req, res, ctx) => 
    res.**once**(ctx.json(replaceDataHereWithDesiredResponse))
  )
)
Run Code Online (Sandbox Code Playgroud)

两次,当然,上面的代码在同一个测试子句中