使用Enzyme和Jest开始测试React组件

4

很遗憾,我所在的工作单位没有对React组件进行单元测试。由于我比较新进入这个行业,没有任何编写软件单元测试的经验。当我试图自学时,我陷入了尴尬的境地,因为我看到的例子要么解释不清楚,要么不适合初学者。最近我使用Enzyme和Jest测试React组件,并认为这种组合看起来很有前途。

我的目标是:我想找出从父组件到子组件的正确测试React属性的方法。我使用Jest和Enzyme,因此解决方案应使用这两个模块的最佳实践。

为了简化问题,我想围绕两个示例组件提出这个问题。让我们假装当这些组件一起使用时,它们会在屏幕上显示一个用户列表。这些组件将被命名为:

  1. UserList(父组件)
  2. UserListItem(子组件)

以下是UserList React组件。为了简化这个示例,我只将传递给子组件的数据放在本地状态中。让我们假设这些数据始终是一个对象数组。

import React, { Component } from 'react'
import UserListItem from './user-list-item'

export default class UserList extends Component {
  constructor(props) {
    super(props)

    this.state = {
      users: [
        {
          userName: 'max',
          age: 24
        },
        {
          userName: 'susan',
          age: 28
        }
      ]
    }
  }

  renderUsers = (list) => {
    return this.state.users.map(user => <UserListItem key={user.userName} user={user} />)
  }

  render() {
    return (
      <ul>
        {this.renderUsers()}
      </ul>
    )
  }
}

现在,这是子组件,UserListItem
import React, { Component } from 'react'

const UserListItem = ({ user }) => {
  return (
    <li>
      <div>
        User: {user.userName}
      </div>
      <div>
        Age: {user.age}
      </div>
    </li>
  )
}

export default UserListItem

从阅读在线教程得知,使用Enzyme进行浅渲染(shallow rendering)是首选方法。我已经明白了其工作原理,但我真正需要的是对props的端到端(end to end)和全面(thorough)测试。

此外,仅检查React组件是否被传递了特定的prop名称是否足够?还是我们还需要创建一些包含虚假数据(dummy data)的假数组(fake array)来提供给子组件?

1个回答

4

对于你当前的组件,我会编写一个测试来确保状态中的元素被正确地渲染,例如:

it('should render two UserListItems', () => {
  const cmp = shallow(<UserList />);

  expect(cmp.find(UserList).length).toBe(2);
})

我还会测试发送给子元素的数据是否正确。在这种情况下,UserListusers 状态应该显示在每个子 UserListItem 的 props 中。

it('should send the correct data', () => {
  const user = { userName: 'test', age: 22 };
  const cmp = shallow(<UserList />);
  cmp.setState({ users: [user] });

  expect(cmp.find(UserListItem).props().user).toBe(user);
})

对于UserListItem组件,我会测试名称和年龄是否被正确地呈现。
it('should render name and age', () => {
  const user = { userName: 'test', age: 22 };
  const cmp = shallow(<UserListItem user={user} />);


  expect(cmp.find('div[children="User: test"]').length).toBe(1);
  expect(cmp.find('div[children="Age: 22"]').length).toBe(1);
})

听起来这正是我需要的,让我了解所有这些工作原理的入门机会。感谢您抽出时间提供答案。我将为所有这些内容编写一个测试,并观察发生了什么。我会将其标记为正确答案。谢谢。 - Dan Zuzevich
2
expect(cmp.find(UserList).props().user).toBe(user); 应该改为 expect(cmp.find(UserListItem).props().user).toBe(user); 吗?否则你正在测试 UserList 上的 props,而它没有任何 props。 - Jonathan Stray
我认为你可能是正确的@JonathanStray。我没有测试过这个确切的例子,但是使用了他的一般答案,所以看起来它被忽略了。我们要建议对此进行编辑吗? - Dan Zuzevich
1
修复了错误。加油团队! - Jonathan Stray
你棒极了。我不知道我们可以自己进行编辑。今天在 SO 上学到了新东西。 - Dan Zuzevich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接