【问题标题】:How to test that the renderItem function returns a <ListItem />?如何测试 renderItem 函数是否返回 <ListItem />?
【发布时间】:2019-01-31 16:56:05
【问题描述】:

我正在使用 React Native 构建我的应用程序,并使用 Jest 和 Enzyme 进行单元测试。如何测试我的&lt;FlatList /&gt;renderItem() 函数?

它从 React-Native-Elements 库返回 &lt;ListItem /&gt;

让我给你示例代码:

import { ListItem } from 'react-native-elements'

export class MyList extends Component {
  const list = [
    {
      name: 'Amy Farha',
      subtitle: 'Vice President'
    },
    {
      name: 'Chris Jackson',
      avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
      subtitle: 'Vice Chairman'
    },
    ... // more items
  ]

  keyExtractor = (item, index) => index

  renderItem = ({ item }) => (
    <ListItem
      title={item.name}
      subtitle={item.subtitle}
      leftAvatar={{
        source: item.avatar_url && { uri: item.avatar_url },
        title: item.name[0]
      }}
    />
  )

  render () {
    return (
      <FlatList
        keyExtractor={this.keyExtractor}
        data={this.state.dataSource}
        renderItem={this.renderItem}
      />
    )
  }
}

我希望能够测试renderItem() 函数。我的问题是,wrapper.instance().renderItem({item: item}) 返回错误:TypeError: wrapper.instance(...).renderItem(...).find is not a function。让我给你我写的测试代码:

describe("component methods", () => {
  let wrapper;
  let props;
  let item;
  beforeEach(() => {
    props = createTestProps();
    wrapper = shallow(<MyList {...props} />);
  });

  describe("renderItem", () => {
    describe("user", () => {
      beforeEach(() => {
        item = {
          name: 'Chris Jackson',
          avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
          subtitle: 'Vice Chairman'
        };
      });

      it("should display the order as a <ListItem />", () => {
        expect(
          wrapper
            .instance()
            .renderItem(item)
            .find("ListItem")
        ).toHaveLength(1);
      });
    });
  });
});

我将如何编写此测试,以便我可以测试该函数是否正确呈现&lt;ListItem /&gt;

【问题讨论】:

    标签: react-native jestjs enzyme listitem react-native-flatlist


    【解决方案1】:

    您也可以使用renderProp 函数进行测试。

    const wrapper = shallow(<YourComponent {...defaultProps} />);
    const flatList = wrapper.find('FlatList');
    
    const item = flatList.renderProp('renderItem')({ item: yourData });
    expect(item).toMatchSnapshot();
    

    【讨论】:

      【解决方案2】:

      你可以用react-native-testing-library测试FlatList

      这是一个例子:

      组件:

      const Item = ({ name ) => <Text>{name}</Text>
      
      class LisItem extends React.Component {
        _keyExtractor = (item: { id: string }) => item.id
      
        render() {
          return (
            <View style={styles.container}>
              {todos && (
                <FlatList
                  data={this.props.todos}
                  keyExtractor={this._keyExtractor}
                  renderItem={({ item: { id, name } }) => (
                    <Item
                      key={id}
                      name={name}
                    />
                  )}
                />
              )}
            </View>
          )
        }
      }
      
      

      单元测试:

      import { render } from 'react-native-testing-library'
      
      const mockDataTodos = [
        {
          id: 'id-1',
          name: 'Todo-1',
        },
        {
          id: 'id-2',
          name: 'Todo-2',
        },
        {
          id: 'id-3',
          name: 'Todo-3',
        },
      ]
      
      describe('Testing FlatList', () => {
          test('Error component should be render when error is true', () => {
            const componentTree = render(
              <ListItem todos={mockDataTodos} />,
            )
      
            expect(componentTree.getAllByType(FlatList).length).toBe(1)
            expect(componentTree.getAllByType(Item).length).toBe(mockDataTodos.length)
          })
      })
      

      希望对您有所帮助!

      【讨论】:

      【解决方案3】:

      renderItem() 返回一个 JSX 元素。 JSX compiles to React.createElement() which returns an object.

      因此,renderItem() 的返回值只是一个对象。

      您可以通过执行以下操作来测试 renderItem() 是否创建了正确的对象:

      it("should display the order as a <ListItem />", () => {
        const element = wrapper
          .instance()
          .renderItem(item);
        expect(element.type).toBe(ListItem);
        expect(element.props).toEqual({
          title: 'Chris Jackson',
          subtitle: 'Vice Chairman',
          leftAvatar: {
            source: { uri: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg' },
            title: 'C'
          }
        });
      });
      

      【讨论】:

      • 这是一个很好的答案
      【解决方案4】:

      所以我不确定您是否从基于类的组件中提取了一些代码,但renderItem 本身就是一个组件。我也许可以给你一些测试代码,你可以根据你的需要调整它,假设你导入了 shallow 并设置了你的 item 变量:

      describe('renderItem', () => {
         it('should display as a ListItem', () => {
             const wrapper = shallow(<renderItem item={item} />);
             expect(wrapper.find(ListItem).length).toEqual(1);
         });
      });
      

      有两个关键点与您的示例不同。一 - 我假设您已经将ListItem 导入到您的测试中。然后,您可以将其直接传递给find。第二位是您要将查找和检查长度的结果传递给expect 并测试它的值。认为它是“我想要测试的”(它可以找到的 ListItem 组件的数量),然后您创建断言 (toEqual(1))。

      反映问题编辑的附加信息

      在您的设置中,我不会费心直接测试renderItem。相反,我会确保对ListItem 进行全面测试,然后断言MyList 如何呈现FlatList。这可以使用expect(wrapper).toMatchSnapshot() 来完成,或者通过断言关于给予FlatList 的道具的一些事情甚至更好。如果你对这一切真的很偏执,也许使用mount而不是浅层来完全渲染它。

      【讨论】:

      • @jimkelly 谢谢你的帮助。没有 renderItem 不是组件本身。如您所见,我编辑了我的问题以反映更改。 renderItem 是来自&lt;MyList /&gt; 的组件方法。
      • @jimkelly 感谢您提供更多信息!让我给你我的背景。我来自 Python 编程,它有一句格言:“显式胜于隐式”。因此,我喜欢避免使用 toMatchSnapshot(),因为在我看来它会促进不良做法(只是隐式检查代码是否已更改,而不是显式测试代码)。 mount 可能是一个很好的研究方法。感谢您的帮助!
      • 这不起作用。你可能误解了这个问题
      猜你喜欢
      • 1970-01-01
      • 2021-06-25
      • 2015-03-30
      • 2016-11-18
      • 2016-12-26
      • 2019-12-11
      • 2018-07-27
      • 2021-05-28
      • 1970-01-01
      相关资源
      最近更新 更多