You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-testing-library配合MSW测试时await后仍处于加载状态的解决方案

已解决

唉!折腾了5小时终于找到问题根源:GraphQL fragments 和 MSW 存在兼容性问题。

问题背景

我使用MSW搭建了Mock GraphQL服务,基础配置如下,我会将其导入测试文件中使用:

// Setup requests interception using the given handlers.
export const server = setupServer(...handlers);

export function setup() {
    beforeAll(() => {
        // Enable the mocking in tests.
        server.listen();
    });

    beforeEach(() => {
        // Ensure Apollo cache is cleared between tests.
        return client.clearStore();
    });

    afterEach(() => {
        // Reset any runtime handlers tests may use.
        server.resetHandlers();
    });

    afterAll(() => {
        // Clean up once the tests are done.
        server.close();
    });
}

我可以确认我的查询请求确实被MSW成功拦截,且响应也正确返回:

graphql.query('getAgenda', (req, res, ctx) => {
    console.debug('in handlers')
    const { id } = req.variables;

    if (id === '1') {
        console.debug('returning res')
        return res(
            ctx.data({
                agenda,
            })
        );
    }
}),

运行时的日志输出如下:

console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:70:10)

  console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:71:10)

  console.debug
    in handlers

      at resolver (src/__tests__/__mocks__/handlers.js:8:11)

  console.debug
    returning res

      at resolver (src/__tests__/__mocks__/handlers.js:12:11)

  console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:70:10)

  console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:71:10)

  console.debug
    in handlers

      at resolver (src/__tests__/__mocks__/handlers.js:8:11)

  console.debug
    returning res

      at resolver (src/__tests__/__mocks__/handlers.js:12:11)

  console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:70:10)

  console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:71:10)

  console.debug
    in handlers

      at resolver (src/__tests__/__mocks__/handlers.js:8:11)

  console.debug
    returning res

      at resolver (src/__tests__/__mocks__/handlers.js:12:11)

  console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:70:10)

  console.debug
    undefined

      at Component (src/pages/Agenda/ViewAgenda.js:71:10)

  console.debug
    in handlers

      at resolver (src/__tests__/__mocks__/handlers.js:8:11)

  console.debug
    returning res

      at resolver (src/__tests__/__mocks__/handlers.js:12:11)

日志中的undefined是我在组件中打印data的输出,我在debugger中也确认data始终没有被成功解析赋值。
我的测试用例代码如下:

it('matches its returned data snapshot', async () => {
    const history = createMemoryHistory();
    history.push('/agenda/1');
    const { asFragment } = render(<ViewAgenda />, { wrapperProps: { history }});


    await screen.findByText('Planerat mötesdatum');
    expect(asFragment(<ViewAgenda />)).toMatchSnapshot();
});

我已经使用了await screen等待元素渲染,也确认问题和路由无关:对应路由的handler被正确触发,组件内的打印日志也正常输出。

问题根因

出现该问题的核心原因是Apollo Client的规范化缓存依赖__typename字段匹配GraphQL fragment的定义类型,而MSW返回的Mock数据默认不会自动注入__typename属性,导致Apollo认为返回的数据和fragment定义不匹配,直接将解析后的data赋值为undefined。

解决方案

  • 手动给Mock数据添加对应类型的__typename属性,比如你的fragment定义在Agenda类型上,就给返回的agenda对象添加__typename: 'Agenda',如果有嵌套子对象也用到了fragment,对应层级也要添加对应类型的__typename。示例修改后的handler代码如下:
graphql.query('getAgenda', (req, res, ctx) => {
    console.debug('in handlers')
    const { id } = req.variables;
    // 给agenda加__typename
    const agendaWithTypename = { ...agenda, __typename: 'Agenda' }
    if (id === '1') {
        console.debug('returning res')
        return res(
            ctx.data({
                agenda: agendaWithTypename,
            })
        );
    }
}),
  • 如果你使用的是MSW v2以上版本,可以开启GraphQL自动注入typename的配置,无需手动给每个返回对象加字段。
  • 临时验证可以先去掉查询语句中的fragment,直接写全所有请求字段,如果此时data可以正常返回,即可确认是fragment匹配导致的问题。

内容的提问来源于stack exchange,提问作者Cookie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 17:54:04