3

I have below Jest config

  jest: {
    configure: {
      testEnvironment: 'jsdom',
      preset: 'ts-jest',
      transform: {...},
      moduleNameMapper: {
        antd: '<rootDir>/__mocks__/antd/index.tsx'
      },
      testMatch: ['<rootDir>/src/**/*.test.(ts|tsx)$'],
    },
  },

In <rootDir>/__mocks__/antd/index.tsx

class Select extends Component<SelectProps> {

  static Option: FC = (props) => <option {...props} data-testid="mock-selectOption"  />;

  render() {
    const {
      ...props
    } = this.props;
    // @ts-ignore
    return <select {...props} data-testid="mock-select" />;
  }
}

I have a Select Component

import React from 'react';
import { Select as MySelect } from 'antd';

const { Option } = MySelect;

export interface SelectOption {
  id: string;
  label: string;
}

interface SelectProp {
  options: SelectOption[];
  selectedOption: string;
  onChange: (key: string) => void;
}

function Select({ options, selectedOption, onChange }: SelectProp) {
  return (
    <MySelect value={selectedOption} onChange={onChange} >
      {options.map((opt) => (
        <Option key={opt.id} value={opt.id}>
          {opt.label}
        </Option>
      ))}
    </MySelect>
  );
}

export default Select;

I have a test case

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

import Select from './Select';

jest.mock('antd', () => {
  const originalModule = jest.requireActual('antd');
  return { ...originalModule };
});

describe('Select', () => {
  const handleChange = jest.fn();
  const mockProps = {
    options: [],
    onChange: handleChange,
  };
  it('render successfully', () => {
    const { getByTestId } = render(<Select {...mockProps} />);
    getByTestId('asca'); // use for debug
  });
});

getByTestId('asca') will make the test case fails, then I see below DOM modal

    TestingLibraryElementError: Unable to find an element by: [data-testid="asca"]

    <body>
      <div>
        <select
          data-testid="mock-select"
        />
      </div>
    </body>

which turns out still using the mock but not the actual antd component.

I've tried to add

     beforeEach(() => {
       jest.unmock('antd');
     });

but still got the same result.

How can I use the actual module instead of mock?

2
  • Why you import Select component from ./Select rather than antd Commented Aug 9, 2022 at 2:38
  • @slideshowp2 This is my custom component. I've updated above. Please check Commented Aug 9, 2022 at 3:18

1 Answer 1

1

Use jest.unmock(moduleName) API is correct,

Indicates that the module system should never return a mocked version of the specified module from require() (e.g. that it should always return the real module).

But you need to know:

When using babel-jest, calls to unmock will automatically be hoisted to the top of the code block.

If you import the Select component and call jest.unmock() in beforeEach hook. When running the test case, the mock Select component has been imported, then the beforeEach hook execute. it's too late for jest to unmock the Select component.

Now, you have two options:

__mocks__/antd/index.tsx:

import { SelectProps } from "antd/lib/select";
import React, { Component, FC } from "react";

class Select extends Component<SelectProps<any>> {
  static Option: FC = (props) => <option {...props} data-testid="mock-selectOption" />;

  render() {
    const { ...props } = this.props;
    // @ts-ignore
    return <select {...props} data-testid="mock-select" />;
  }
}

Select.tsx:

import React from 'react';
import { Select as MySelect } from 'antd';

const { Option } = MySelect;

export interface SelectOption {
  id: string;
  label: string;
}

interface SelectProp {
  options: SelectOption[];
  selectedOption: string;
  onChange: (key: string) => void;
}

function Select({ options, selectedOption, onChange }: SelectProp) {
  return (
    <MySelect data-testid='asca' value={selectedOption} onChange={onChange}>
      {options.map((opt) => (
        <Option key={opt.id} value={opt.id}>
          {opt.label}
        </Option>
      ))}
    </MySelect>
  );
}

export default Select;

1. Call jest.unmock() API in module scope of test file(Put it after the import statement is ok, it will be hoisted to the top of the code block)

import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Select from './Select';

jest.unmock('antd');

describe('Select', () => {
  it('render successfully', async () => {
    const handleChange = jest.fn();
    const mockProps = {
      options: [],
      onChange: handleChange,
      selectedOption: '',
    };
    const { getByTestId } = render(<Select {...mockProps} />);
    expect(getByTestId('asca')).toBeInTheDocument();
  });
});

2. Call jest.unmock() API in beforeEach hook or it functional scope, then dynamic import the Select component.(Dynamic import statement must put after the jest.unmock() API)

import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';

describe('Select', () => {
  it('render successfully', async () => {
    jest.unmock('antd');
    const Select = (await import('./Select')).default
    const handleChange = jest.fn();
    const mockProps = {
      options: [],
      onChange: handleChange,
      selectedOption: '',
    };
    const { getByTestId } = render(<Select {...mockProps} />);
    expect(getByTestId('asca')).toBeInTheDocument();
  });
});

Test result:

 PASS  stackoverflow/73274190/Select.test.tsx (11.55 s)
  Select
    ✓ render successfully (1156 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        12.049 s, estimated 13 s

jest.config.js:

module.exports = {
  preset: 'ts-jest/presets/js-with-ts',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['jest-extended'],
  setupFiles: ['./jest.setup.js'],
};

package version:

"antd": "^4.16.12",
"jest": "^26.6.3",
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.