'React - How to mock useFormContext (react-hook-form)
I am using useFormContext in one the child component. this is the code for it:
const { register } = useFormContext<CustomerProfileFormData>();
How can I Mock useFormContext so that I can test child component. this is the test
it('should render properly', () => {
render(<AddressDetails isEdit={false} />);
expect(screen.getByTestId('address-details')).toBeInTheDocument();
});
I am getting this error TypeError: Cannot destructure property 'register' of '(0 , _reactHookForm.useFormContext)(...)' as it is null.Jest.
which makes sense since I did not mock useFormContext . How can I Mock it? any help will be appreciated.
Solution 1:[1]
You must provide a context for this to work as a unit test. If you need to "unit-test" this particular AddressDetails component, then mock out some context for it. I cannot give you a specific answer without more context related to your component. When context is involved, I typically add a mock wrapper component. For "react-hook-form" it appears a few methods are exposed. If you want to mock those for unit-testing, then do it:
jest.mock("react-hook-form", () => ({
...jest.requireActual("react-hook-form"),
register: jest.fn(),
handleSubmit: jest.fn(),
// ...whatever APIs you use in your component
}))
If you want to test that your component "integrates" with your vendor packages, then you are trying to run "integration-tests." In that case, I would suggest reading the documentation for the vendor library you use. Please read your vendor's very comprehensive documentation before asking the community. It appears they made a huge effort to answer your question within those docs.
Solution 2:[2]
I found a solution that works for me:
jest.mock("react-hook-form", () => ({
...jest.requireActual("react-hook-form"),
useFormContext: () => ({
handleSubmit: () => jest.fn(),
getValues: () => jest.fn(),
});
}));
Solution 3:[3]
You can either mock the context methods as indicated in other responses, or you can provide your component with an actual FormContext by creating an ad hoc wrapper component inside your test like this:
it('should do something', () => {
const Wrapper = (props) => {
const formMethods = useForm<CustomerProfileFormData>();
return (
<FormProvider {...formMethods}>
{props.children}
</FormProvider>
);
};
render(
<Wrapper>
<AddressDetails />
</Wrapper>
);
// your assertions here ...
})
If you want to verify that your components behaves correctly upon form values, you could e.g. override the getValues method with preconfigured data.
const mockedGetValues = (key: string) => {
// return test data for form key
}
return (
<FormProvider {...formMethods} getValues={mockedGetValues}>
{props.children}
</FormProvider>
);
Solution 4:[4]
To make the useFormContext method work inside tests, RHF recommend wrapping it with <FormProvider> (Github-How to Test FormProvider / useFormContext).
Wrap your component with <FormProvider> and provide the required methods like this:
render(
<FormProvider {...({ setValue: () => jest.fn() } as any)}>
<AddressDetails isEdit={false} />
</FormProvider>
);
Solution 5:[5]
To mock react-hook-form v7 you can do as follow
jest.mock('react-hook-form', () => ({
...jest.requireActual('react-hook-form'),
useFormContext: () => ({
handleSubmit: () => jest.fn(),
control: {
register: jest.fn(),
unregister: jest.fn(),
getFieldState: jest.fn(),
_names: {
array: new Set('test'),
mount: new Set('test'),
unMount: new Set('test'),
watch: new Set('test'),
focus: 'test',
watchAll: false,
},
_subjects: {
watch: jest.fn(),
array: jest.fn(),
state: jest.fn(),
},
_getWatch: jest.fn(),
_formValues: ['test'],
_defaultValues: ['test'],
},
getValues: () => {
return [];
},
setValue: () => jest.fn(),
formState: () => jest.fn(),
watch: () => jest.fn(),
}),
Controller: () => [],
useSubscribe: () => ({
r: { current: { subject: { subscribe: () => jest.fn() } } },
}),
}));
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | taystack |
| Solution 2 | Tomerikoo |
| Solution 3 | Johannes Charra |
| Solution 4 | goamn |
| Solution 5 |
