Jest Mock React 组件仅在某些测试中

Nor*_*ldt 7 javascript unit-testing reactjs jestjs react-testing-library

这个问题真的很好:Jest Mock module per test

它只是没有回答我的问题,即如何仅在一个测试中模拟它并使用原始组件保留其余部分。

如果我想对快照进行一些模拟而不是对其他测试进行一些模拟,那就有意义了

这是我目前的尝试

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

jest.mock('components/Photo', () =>
  jest.fn(() => jest.requireActual('components/Photo'))
)
import Photo from 'components/Photo'

import PhotoGrid from '.'

beforeEach(() => {
  Photo.mockReset()
})

test('default renders 9 photos if provided 9', () => {
  const photos = [...Array(9).keys()]
  const { getAllByTestId, debug } = render(<PhotoGrid photos={photos} />)

  debug()
  expect(getAllByTestId(PHOTO_COMP_TEST_ID)).toHaveLength(9)
})

test('renders with masonry grid style', () => {
  Photo.mockImplementation(() => <div />)
  const photos = [...Array(9).keys()]
  const { container, debug } = render(<PhotoGrid photos={photos} />)

  debug()

  expect(container).toMatchInlineSnapshot(`
    <div>
      ... 
    </div>
  `)
})
Run Code Online (Sandbox Code Playgroud)

这是要测试的组件

import React from 'react'
import Masonry from 'react-masonry-css'
import './index.css'

import Photo from 'components/Photo'

function PhotoGrid({ photos, numberOfPhotos = 9 }) {
  const imgs = photos ? photos.slice(0, numberOfPhotos) : []

  const breakpointColumnsObj = {
    default: 4,
    1300: 3,
    900: 2,
    700: 1,
  }

  return (
    <Masonry
      breakpointCols={breakpointColumnsObj}
      className="my-masonry-grid"
      columnClassName="my-masonry-grid_column"
    >
      {imgs &&
        imgs.map(({ id, secret, server, farm }, index) => (
          <div key={index} className="masonry-item">
            <Photo id={id} secret={secret} server={server} farm={farm} />
          </div>
        ))}
    </Masonry>
  )
}

export default PhotoGrid
Run Code Online (Sandbox Code Playgroud)

小智 6

jest.mock(...) 您想要在测试之一中模拟的组件。

使用 jest.requireActual(...) 实现默认行为。

使用mockImplementation来实现自定义行为。

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

jest.mock('components/Photo')
import Photo from 'components/Photo'

import PhotoGrid from '.'

// This maintains the original implementation for tests. 
// This step is important because if not done, it will
// result in empty render errors.
beforeEach(() => {
  Photo.mockImplementation(jest.requireActual('components/Photo'));
}) 
 

// This test will use original implementation of 'components/Photo'
test('default renders 9 photos if provided 9', () => {
  const photos = [...Array(9).keys()]
  const { getAllByTestId, debug } = render(<PhotoGrid photos={photos} />)

  debug()
  expect(getAllByTestId(PHOTO_COMP_TEST_ID)).toHaveLength(9)
})

// This test will use the mocked implementation of 'components/Photo'
test('renders with masonry grid style', () => {
  Photo.mockImplementation(() => <div />)
  const photos = [...Array(9).keys()]
  const { container, debug } = render(<PhotoGrid photos={photos} />)

  debug()

  expect(container).toMatchInlineSnapshot(`
    <div>
      ... 
    </div>
  `)
})
Run Code Online (Sandbox Code Playgroud)

  • 当我执行此操作时,我收到“TypeError: SpecificMockImpl.apply is not a function”。 (4认同)

dan*_*onn 6

我没有添加评论的权限,所以我将其留在这里。

我已经尝试了 Han Daniels 提供的解决方案,但收到错误:

TypeError: specificMockImpl.apply is not a function

.default我通过添加之后修复了它,jest.requireActual('components/Photo')因为照片是默认导出。

所以它是:jest.requireActual('components/Photo').default