当前位置: 首页 > 知识库问答 >
问题:

如何用酶、笑话、重组、反应测试组件中的功能

吕树
2023-03-14

好的,我有点困惑于如何使用enzyme/jest测试我的组件的功能。仍在学习如何测试我的组件——我可以编写简单的测试,但现在我需要让它们更复杂。

我想知道测试组件函数是否被正确调用以及它们是否按预期更新状态道具的最佳方法。我发现很棘手的是,我的函数和状态都存在于我的组件的道具中。

如果我需要使用间谍,我想最好知道如何使用笑话,但是如果像西农或贾斯敏这样的特工更适合这份工作,我愿意接受(只要让我知道为什么,这样我就能更好地理解)。

例如,我有一个UserDetails组件

const UserDetails = ({
 userInfo,
 onUserInfoUpdate,
 className,
 error,
 title,
 primaryBtnTitle,
 submit,
 secondaryBtnTitle,
 secondaryBtnFunc,
 ...props
}) => (
 <div className={className}>
   <div className="user-details-body">
     <Section title="User details">
       <TextInput
         className="firstName"
         caption="First Name"
         value={userInfo.first}
         onChange={onUserInfoUpdate('first')}
         name="first-name"
         min="1"
         max="30"
         autoComplete="first-name"
       />
       <TextInput
         className="lastName"
         caption="Last Name"
         value={userInfo.last}
         onChange={onUserInfoUpdate('last')}
         name="last-name"
         min="1"
         max="30"
         autoComplete="last-name"
       />
     </Section>
   </div>

   <div className="errorBar">
     {error && <Alert type="danger">{error}</Alert>}
   </div>

   <ActionBar>
     <ButtonGroup>
       <Button type="secondary" onClick={secondaryBtnFunc}>
         {secondaryBtnTitle}
       </Button>
       <Button type="primary" onClick={submit}>
         {primaryBtnTitle}
       </Button>
     </ButtonGroup>
   </ActionBar>
 </div>  

文本输入包括:

<label className={className}>
 {Boolean(caption) && <Caption>{caption}</Caption>}
 <div className="innerContainer">
   <input value={value} onChange={updateValue} type={type} {...rest} />     
 </div>
</label>

下面是我的index.js文件的示例代码,它将我的with State和with Handler组成我的组件:

import UserDetails from './UserDetails'
import { withState, withHandlers, compose } from 'recompose'

export default compose(
  withState('error', 'updateError', ''),
  withState('userInfo', 'updateUserInfo', {
    first: '',
    last: '',
  }),
  withHandlers({
    onUserInfoUpdate: ({ userInfo, updateUserInfo }) => key => e => {
      e.preventDefault()
      updateCardInfo({
        ...cardInfo,
        [key]: e.target.value,
      })
    },
    submit: ({ userInfo, submitUserInfo }) => key => e => {
      e.preventDefault()
      submitUserInfo(userInfo) 
      //submitUserInfo is a graphQL mutation
      })
    }  
  }) 
)

到目前为止,我的测试文件是这样的:

import React from 'react'
import { mount } from 'enzyme' 
import UserDetails from './'
import BareUserDetails from './UserDetails'

describe('UserDetails handlers', () => {
  let tree, bareTree

  beforeEach(() => {
    tree = mount(
      <ThemeProvider theme={theme}>
        <UserDetails />
      </ThemeProvider>
    )
    bareTree = tree.find(BareUserDetails)
  })

  it('finds BareUserDetails props', () => {
    console.log(bareTree.props())
    console.log(bareTree.props().userInfo)
    console.log(bareTree.find('label.firstName').find('input').props())
  })

})

控制台日志返回我关于我期望看到的正确信息,当我呼吁他们:

//console.log(bareTree.props())
   { error: '',
      updateError: [Function],
      userInfo: { first: '', last: '' },
      updateUserInfo: [Function],
      onUserInfoUpdate: [Function] }

//console.log(bareTree.props().userInfo)
   { first: '', last: '' }

//console.log(bareTree.find('label.firstName').find('input).props()
   { value: '',
      onChange: [Function],
      type: 'text',
      name: 'first-name',
      min: '1',
      max: '30',
      autoComplete: 'first-name' }

现在的问题是我如何使用它们,以及最好的方法。我是否使用我的函数,或者我只是检查是否调用了onChange?

我尝试过这个,我得到以下结果:

  it('Input element updates userInfo with name onChange in FirstName input', () => {
    const firstNameInput = bareTree.find('label.firstName').find('input)
    ccNameInput.simulate('change', {target: {value: 'John'}})
    expect(ccNameInput.prop('onChange')).toHaveBeenCalled()
  })

在我的终端,我得到:

 expect(jest.fn())[.not].toHaveBeenCalled()

    jest.fn() value must be a mock function or spy.
    Received:
      function: [Function anonymous]

然而,如果我试图用Jest创建一个spyOn,我得到一个错误,它无法读取未定义的函数。

我试过spy=jest。spyOn(UserDetails.prototype,'onUpdateUserInfo')spy=jest。spyOn(BareUserDetails.prototype,'onUpdateUserInfo'),它们都会抛出错误。

共有1个答案

韶和璧
2023-03-14

我相信您应该分别测试哑组件(User细节)和HOC。对于哑组件,您希望用呈现组件并注入道具。要模拟onUserInfoUpdate,您需要执行const onUserInfoUpdate=jest.fn();

你想要一些类似于……的东西。。。。

import React from 'react'
import { shallow } from 'enzyme' 
import UserDetails from './UserDetails'

const onUserInfoUpdate = jest.fn(); // spy
const props = {
  onUserInfoUpdate,
  // list all your other props and assign them mock values
};

describe('UserDetails', () => {
  let tree;

  beforeAll(() => {
    tree = shallow(<UserDetails {...props} />)
  });

  it('should invoke the onUserInfoUpdate method', () => {
    const firstNameInput = tree.find('label.firstName').find('input');
    firstNameInput.simulate('change', { target: { value: 'John' } });

    expect(onUserInfoUpdate).toHaveBeenCalledWith('first');
  });
});
 类似资料:
  • 我有以下组成部分: 现在我正在尝试编写一个单元测试来检查if条件(根据.to属性返回IndexLink或Link): 但我似乎无法测试函数的确切jsx返回,因为当我使用控制台时。记录我得到的其中一个返回: {$$typeof':Symbol(react.element),type:'div',key:'/',ref:null,props:{className:'navbar link contai

  • 问题内容: 我正在使用酶+摩卡+柴来测试我的react-redux项目。酶提供浅浅以测试组件的行为。但是我没有找到测试路由器的方法。我正在使用如下的react- router: 我要测试此路由参考组件。如何在reactjs项目中对其进行测试? 编辑1 我正在使用作为路由器框架。 问题答案: 您可以将路由器包装在组件中以对其进行测试。 Routes.jsx index.js 然后,您必须对组件进行浅

  • 问题内容: 我有一个React组件(为了演示该问题,对此进行了简化): 现在,我要测试提供的值的调用。 为此,我想创建一个代替组件方法的笑话模拟函数。 到目前为止,这是我的测试用例: 但是我在控制台中得到的只是: 语法错误 所以我的问题是,如何正确地用酶模拟组分方法? 问题答案: 可以通过以下方式模拟该方法: 您还需要在被测组件的包装器上调用.update,以便正确注册模拟功能。 语法错误来自错误

  • 问题内容: 我正在尝试测试React组件的样式属性。在测试中获取样式参数的最佳方法是什么? 目前,我最好的选择是测试HTML是否包含字符串,但是我认为有一个更好的选择。 案件: 要测试的组件是: 问题答案: 您可以使用此方法。它返回ReactElement。

  • 我在学反应。我读过一篇文章,建议我们使用函数组件,而不是扩展react.component的类,所以我跟着做了。我也使用箭头函数而不是函数关键字。即: 有没有一种方法可以使用setState()来代替setName()、setId()、…等?或者任何建议? 非常感谢!

  • 我想通过剧作家选择一个选项,但我不能选择一个选项。什么是错的? 梅 测试