简体   繁体   English

React 上下文测试 - 在 HOC 中模拟消费者

[英]React Context testing - mocking Consumer in HOC

I am trying to test my component which is consuming data from context via HOC.我正在尝试测试我的组件,该组件通过 HOC 使用上下文中的数据。

Here is setup: Mocked context module /context/__mocks__这是设置:模拟上下文模块/context/__mocks__

const context = { navOpen: false, toggleNav: jest.fn() } 

export const AppContext = ({
    Consumer(props) {
        return props.children(context)
    }
})

Higher OrderComponent /context/withAppContext高阶组件/context/withAppContext

import React from 'react'
import { AppContext } from './AppContext.js'

/**
 * HOC with Context Consumer
 * @param {Component} Component 
 */
const withAppContext = (Component) => (props) => (
    <AppContext.Consumer>
        {state => <Component {...props} {...state}/>}
    </AppContext.Consumer>
) 

export default withAppContext

Component NavToggle组件NavToggle

import React from 'react'
import withAppContext from '../../../context/withAppContext'

import css from './navToggle/navToggle.scss'

const NavToggle = ({ toggleNav, navOpen }) => (
    <div className={[css.navBtn, navOpen ? css.active : null].join(' ')} onClick={toggleNav}>
        <span />
        <span />
        <span />
    </div>
)

export default withAppContext(NavToggle)

And finally Test suite /navToggle/navToggle.test最后测试套件/navToggle/navToggle.test

import React from 'react'
import { mount } from 'enzyme'

beforeEach(() => {
  jest.resetModules()
}) 

jest.mock('../../../../context/AppContext')


describe('<NavToggle/>', () => { 
  it('Matches snapshot with default context', () => {    
        const NavToggle = require('../NavToggle')        
        const component = mount( <NavToggle/> )
        expect(component).toMatchSnapshot()
  })
})

Test is just to get going, but I am facing this error: Warning: Failed prop type: Component must be a valid element type! in WrapperComponent测试只是为了开始,但我面临这个错误: Warning: Failed prop type: Component must be a valid element type! in WrapperComponent Warning: Failed prop type: Component must be a valid element type! in WrapperComponent Which I believe is problem with HOC, should I mock that somehow instead of the AppContext, because technically AppContext is not called directly by NavToggle component but is called in wrapping component. Warning: Failed prop type: Component must be a valid element type! in WrapperComponent我认为 HOC 存在问题,我应该以某种方式模拟它而不是 AppContext,因为技术上 AppContext 不是由 NavToggle 组件直接调用,而是在包装组件中调用。

Thanks in advance for any input.提前感谢您的任何意见。

So I solved it.所以我解决了它。

There were few issues with my attempt above.我上面的尝试几乎没有问题。

  1. require does not understand default export unless you specify it require 不理解默认导出,除非您指定它
  2. mounting blank component returned error安装空白组件返回错误
  3. mocking AppContext with __mock__ file caused problem when I wanted to modify context for test当我想修改测试上下文时,使用__mock__文件__mock__ AppContext 会导致问题

I have solved it following way.我已经通过以下方式解决了它。 I created helper function mocking AppContext with custom context as parameter我使用自定义上下文作为参数创建了模拟 AppContext 的辅助函数

export const defaultContext = { navOpen: false, toggleNav: jest.fn(), closeNav: jest.fn(), path: '/' } 

const setMockAppContext = (context = defaultContext) => {
    return jest.doMock('../context/AppContext', () => ({
        AppContext: {
            Consumer: (props) => props.children(context)
        }
    }))  
}
export default setMockAppContext

And then test file ended looking like this然后测试文件看起来像这样

import React from 'react'
import { shallow } from 'enzyme'
import NavToggle from '../NavToggle'
import setMockAppContext, { defaultContext } from '../../../../testUtils/setMockAppContext'

beforeEach(() => {
  jest.resetModules()
}) 

describe('<NavToggle/>', () => { 
  //...   
  it('Should have active class if context.navOpen is true', () => {
    setMockAppContext({...defaultContext, navOpen: true})
    const NavToggle = require('../NavToggle').default //here needed to specify default export
    const component = shallow(<NavToggle/>)
    expect(component.dive().dive().hasClass('active')).toBe(true) //while shallow, I needed to dive deeper in component because of wrapping HOC   
  })
  //...
})

Another approach would be to export the component twice, once as decorated with HOC and once as clean component and create test on it, just testing behavior with different props.另一种方法是将组件导出两次,一次用 HOC 装饰,一次作为干净的组件并在其上创建测试,只用不同的 props 测试行为。 And then test just HOC as unit that it actually passes correct props to any wrapped component.然后只测试 HOC 作为单元,它实际上将正确的 props 传递给任何包装的组件。

I wanted to avoid this solution because I didn't want to modify project file(even if it's just one word) just to accommodate the tests.我想避免这种解决方案,因为我不想为了适应测试而修改项目文件(即使它只是一个词)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM