Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking Child in React Native using Jest

I have the following parent screen/component Employees.tsx

import PasswordForm from '../../components/Forms/PasswordForm'

...
<View style={ stylesheet.modalWrapper }>
    <PasswordForm
        errorMessage={ auth.error }
        isWorking={ auth.isWorking }
        onCancel={ toggleModal }
        onSubmit={ customSubmitHandler }
    />
</View>

<PasswordForm /> is a child component that is a decorated form using reduxForm to connect, imported into the parent in the standard way.

PasswordForm.tsx

const PasswordForm = reduxForm({
    form: 'password-form'
})(PasswordFormStatic)

In my tests, I am not interested in the functionality of this child component <PasswordForm> so I want to mock that component, and just make sure that the mocked component is still present in the snapshot test of the parent component (Employees.tsx).

jest.mock() I thought would handle this. This is Employees.spec.tsx

describe('Employees Scene', () => {
    let wrapper
    const requestAuthToken = jest.fn()

    jest.mock('../../components/Forms/PasswordForm', () => {
        const mockedPasswordForm = () => null
        return mockedPasswordForm
    })

However, I still get the error that Invariant Violation: Could not find "store" in either the context or props... which is really a complaint about the child.

So it appears jest.mock() here is not mocking my component? As it is still trying to render and complain about the lack of a store.

How do I properly mock components (specifically children) in Jest with React-Native?

like image 312
Aleski Avatar asked Jul 30 '26 11:07

Aleski


1 Answers

Your problem is not related to react or reduc, but to the javascript import mecanism :

Because PasswordForm is imported on the top of Employees.tsx file, and then Employees is (likely) imported at the top of your test case, this makes the load happen in this order : PasswordForm > Employees > Employees.spec (because imports happen before any other statements)

The mock you create in the test case is unknown by the Employees class.

Jest provides a way to handle this scenario, Ill do it with some simple code that illustrate perfectly the problem

First, lets reproduce the issue

a simple function returning 1

./src/A.js

const fn = () => 1
export default fn

a simple function, using the A defined before

./src/B.js

import A from 'A'
const B = () => A() + 1
export default B

finally a test for B function that tries to mock A as you do in your case

./test/B.test.js

import B from 'B'
test('Try to mock A on the fly', () => {
    jest.mock('../src/A', () => 0)
    expect(B(1)).toBe(1)
})

this results in

FAIL  test\B.test.js
  × Try to mock A on the fly (10ms)

  ● Try to mock A on the fly

    expect(received).toBe(expected) // Object.is equality

    Expected value to be:
      1
    Received:
      2

      2 | test('Try to mock A on the fly', () => {
      3 |     jest.mock('../src/A', () => 0)
    > 4 |     expect(B(1)).toBe(1)
      5 | })

      at Object.<anonymous> (test/B.test.js:4:18)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        2.598s

Now if you use jest mock module as explained here https://facebook.github.io/jest/docs/en/manual-mocks.html

By creating a new file

a mock for A (the '_ _ mocks _ _' folder name is important)

./__mocks__/A.mock.js

const A = jest.fn(() => 0)
export default A

and modifying your test file to

import A from 'A'
import B from 'B'
jest.mock('A')
test('use jest mock for A', () => {
    expect(B(1)).toBe(1)
})

you will end up with what you want

PASS  test\B.test.js
  √ use jest mock for A (4ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.57s  
like image 113
Ji aSH Avatar answered Aug 02 '26 07:08

Ji aSH



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!