【问题标题】:Mocking Child in React Native using Jest使用 Jest 在 React Native 中模拟孩子
【发布时间】:2023-04-02 23:32:01
【问题描述】:

我有以下父屏幕/组件Employees.tsx

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

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

&lt;PasswordForm /&gt; 是一个子组件,它是一个使用reduxFormconnect 的装饰表单,以标准方式导入到父组件中。

PasswordForm.tsx

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

在我的测试中,我对这个子组件&lt;PasswordForm&gt; 的功能不感兴趣,所以我想模拟那个组件,并确保被模拟的组件仍然存在于父组件的快照测试中(@ 987654329@)。

jest.mock() 我认为会处理这个问题。这是Employees.spec.tsx

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

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

但是,我仍然收到Invariant Violation: Could not find "store" in either the context or props... 的错误,这确实是对孩子的抱怨。

所以看来jest.mock() 不是在嘲笑我的组件?因为它仍在尝试渲染并抱怨缺少商店。

如何在 Jest 中使用 React-Native 正确模拟组件(特别是子组件)?

【问题讨论】:

    标签: reactjs unit-testing react-native jestjs


    【解决方案1】:

    您的问题与 react 或 reduc 无关,而是与 javascript 导入机制有关:

    因为 PasswordForm 是在Employees.tsx 文件的顶部导入的,然后Employees 是(可能)在测试用例的顶部导入的,这使得负载按以下顺序发生:PasswordForm >Employees >Employees.spec(因为导入发生在任何其他语句之前)

    Employees 类不知道您在测试用例中创建的模拟。

    Jest 提供了一种处理这种情况的方法,我会用一些简单的代码来完美地说明问题

    首先,让我们重现问题

    一个返回 1 的简单函数

    ./src/A.js
    
    const fn = () => 1
    export default fn
    

    一个简单的函数,使用之前定义的A

    ./src/B.js
    
    import A from 'A'
    const B = () => A() + 1
    export default B
    

    最后是一个 B 函数的测试,它试图像你在你的情况下那样模拟 A

    ./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)
    })
    

    这导致

    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
    

    现在,如果您按照此处的说明使用 jest mock 模块 https://facebook.github.io/jest/docs/en/manual-mocks.html

    通过创建一个新文件

    A 的模拟('_ _ mocks _ _' 文件夹名称很重要)

    ./__mocks__/A.mock.js
    
    const A = jest.fn(() => 0)
    export default A
    

    并将您的测试文件修改为

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

    你会得到你想要的

    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  
    

    【讨论】:

    • 哦,好的。那么在 mocks 文件夹中创建一个同名的文件(是在根目录中吗?),然后从中导出一个jest.fn()
    • 我把 mocks 放在我的基本目录中,它一直告诉我在其中找不到文件(找不到模块)
    猜你喜欢
    • 1970-01-01
    • 2019-10-08
    • 2018-05-05
    • 2017-06-08
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    相关资源
    最近更新 更多