【问题标题】:Fetch never returns data when msw (Mock Service Worker) intercepts request当 msw (Mock Service Worker) 拦截请求时,Fetch 永远不会返回数据
【发布时间】:2022-03-17 22:38:59
【问题描述】:

我目前正在使用 next/jest 来设置我的环境,包括 msw 和 @testing@library/react。我的测试看起来像:

import { TestComponent } from '../../../components/TestComponent'
import React from 'react'
import { render } from '@testing-library/react'

test('Test TestComponent', function () {
  const wrap = render(<TestComponent />)
  expect(wrap.container.childElementCount).toBe(2)
})

我的 jest.config.js 看起来像:

const nextJest = require('next/jest')

const createJestConfig = nextJest({
  dir: './',
})

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/test_utils/setup-env.js'],
  moduleDirectories: ['node_modules', '<rootDir>/'],
  testEnvironment: 'jest-environment-jsdom',
}

module.exports = createJestConfig(customJestConfig)

我的 setup-env.js 看起来像这样:

import '@testing-library/jest-dom'
import { server } from './server.js'

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

我的组件看起来像这样......

import React, { useEffect, useState } from 'react'

import { useSWRFetch } from '../../../hooks'

export const TestComponent = (): JSX.Element => {
  const [data, setData] = useState([])
  const dataInfo = useSWRFetch({
    endpoint: `${process.env.NEXT_PUBLIC_API_URL}/v1/endpoint`,
  })

  useEffect(() => {
    if (dataInfo) {
      setDomains(dataInfo.data)
    }
  }, [dataInfo])
  return (
    <>
        {data &&
          data.map((item, idx) => (
                  <div>
                    <p>{item.count | 0}</p>
                    <p>Job</p>
                  </div>
          ))}
    </>
  )
}

当我运行测试时,我收到以下错误...

ReferenceError: fetch is not defined

但是,当我对 dataInfo.data 的值时,它始终是未定义的。

我有一个 SWR 使用的 fetcher 函数,如下所示:

async function fetcher(...args) {
  console.log("BEFORE REQUEST")
  const url = args[0]
  const token = args[1]
  const method = args.length > 2 ? args[2] : 'GET'
  const body = args.length > 3 ? { body: JSON.stringify(args[3]) } : {}
  const res = await fetch(url, {
    method: method,

    headers:
      method != 'GET'
        ? {
            Authorization: `bearer ${token}`,
            'Content-Type': 'application/json',
          }
        : {
            Authorization: `Bearer ${token}`,
          },
    ...body,
  })

  console.log("AFTER REQUEST")

  if (!res.ok) {
    const error = new Error('An error occurred while fetching the data.')
    // Attach extra info to the error object.
    error.info = await res.json()
    error.status = res.status
    throw error
  }

  return res.json()
}

function useSWRFetch({ endpoint, token, options = null, condition=true }) {
  const { data, error, mutate } = useSWR(token && condition ? [endpoint, token] : null, fetcher, options)

  return {
    mutate: mutate,
    data: data,
    isLoading: !error && !data,
    error: error,
  }
}

但是它永远不会到达第二个控制台,在请求被拦截后请求之后。

【问题讨论】:

    标签: reactjs jestjs next.js react-testing-library msw


    【解决方案1】:

    根据错误消息,您没有在测试中填充 fetch。 Node.js 没有 fetch 函数,因为它是一个仅限浏览器的 API。如果您正在测试使用 fetch 的代码(您的 fetcher 确实如此),您需要始终填充该函数。这通常由 Create React App 等框架完成,但如果您使用自定义设置,则必须手动完成。

    我推荐使用whatwg-fetch:

    // setup-env.js
    import 'whatwg-fetch'
    
    // ...the rest of your test setup
    

    一旦fetch 被填充,Jest 将能够运行您的测试,并且您将得到模拟的响应。

    【讨论】:

    • 我添加了whatwg-fetch,但是虽然它被拦截了它仍然没有返回响应
    • 为什么这被否决了?这是一个正确的答案。听起来@Kalimantan 问题在于处理程序没有正确定义
    猜你喜欢
    • 1970-01-01
    • 2022-12-27
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    相关资源
    最近更新 更多