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?
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 tounmockwill 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",
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With