React Context测试-在HOC中模拟消费者

时间:2018-12-04 20:27:51

标签: javascript reactjs jestjs enzyme

我正在尝试测试通过HOC消耗上下文数据的组件。

此处已设置: 模拟的上下文模块NULL

/context/__mocks__

高阶组件const context = { navOpen: false, toggleNav: jest.fn() } export const AppContext = ({ Consumer(props) { return props.children(context) } })

/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

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)

/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() }) }) 我认为这是HOC的问题,我应该以某种方式而不是AppContext来模拟它,因为从技术上讲,AppContext不是由NavToggle组件直接调用,而是在包装组件中调用。

首先感谢您的任何输入。

1 个答案:

答案 0 :(得分:0)

所以我解决了。

我上面的尝试几乎没有问题。

  1. require不能理解默认导出,除非您指定了默认设置
  2. 安装空白组件返回错误
  3. 当我想修改测试环境时,用__mock__文件模拟AppContext引起了问题

我已经按照以下方式解决了。 我创建了以自定义上下文为参数的模拟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

然后测试文件看起来像这样

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

另一种方法是将组件导出两次,一次用HOC装饰,一次导出为干净组件,然后在其上创建测试,仅使用不同的道具测试行为。然后以单元为单位对HOC进行实际测试,以将它正确地传递给任何包装的组件。

我想避免这种解决方案,因为我不想为了容纳测试而修改项目文件(即使只是一个字)。