我试图了解单元测试的工作原理,并构建了一个小的React应用程序,该应用程序呈现了Pokemon的列表。
我正在尝试做的是编写一个单元测试,以检查列表是否正确呈现。但是,生成的快照显示它仅呈现“正在加载...”文本,这是在等待来自API的响应时应执行的操作。
我究竟做错了什么?

PokemonList.test.js

import React from 'react';
import PokemonList from '../components/PokemonList';
import renderer from 'react-test-renderer';

describe('PokemonList component renders a list of Pokemon', () => {
    it('renders correctly', () => {
        const fetched = true;
        const loading = true;
        const species = [{
            "0": {"name": "bulbasaur"},
            "1": {"name": "ivysaur"},
            "2": {"name": "venusaur"}
        }];
        const rendered = renderer.create(
            <PokemonList fetched={fetched} loading={loading} species={species} />
        );
        expect(rendered.toJSON()).toMatchSnapshot();
    });
});


PokemonList.js

// The PokemonList component show nothing when it mounts for the first time.
// But right before it mounts to the DOM, it makes an API call to fetch the
// first 151 Pokemon for the API and then displays them using the Pokemon component.

import React from 'react';
import Pokemon from './Pokemon';

class PokemonList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            species: [],
            fetched: false,
            loading: false,
        };
    }

    componentWillMount() {
        this.setState({
            loading: true
        });
        fetch('http://pokeapi.co/api/v2/pokemon?limit=151').then(res=>res.json())
        .then(response=>{
            this.setState({
                species: response.results,
                loading: true,
                fetched: true
            });
        });
    }

    render() {
        const {fetched, loading, species} = this.state;
        let content ;
        if (fetched) {
            content = <div className="pokemon--species--list">{species.map((pokemon, index) => <Pokemon key={pokemon.name} id={index+1} pokemon={pokemon} />)}</div>
        } else if (loading && !fetched) {
            content = <p className="loading"> Loading ...</p>
        } else {
            content = <div/>
        }
        return (
            <div>
                {content}
            </div>
        )
    }
}

export default PokemonList;


PokemonList.test.js.snap

exports[`PokemonList component renders a list of Pokemon renders correctly 1`] = `
<div>
  <p
    className="loading">
     Loading ...
  </p>
</div>
`;

最佳答案

您正在尝试通过道具来更改PokemonList组件中的状态,但是PokemonList不会对道具做任何事情,因此状态不会改变。设置状态并测试PokemonList组件的一种方法(在我看来是最简单的方法)是使用Enzymeenzyme-to-json。这是一个例子:

import React from 'react';
import PokemonList from '../components/PokemonList';
// Importing shallow and toJson.
import {shallow} from "enzyme";
import toJson from "enzyme-to-json";

describe('PokemonList component renders a list of Pokemon', () => {
  it('renders correctly', () => {
    const wrapper = shallow(<PokemonList/>);
    const fetched = true;
    // You can omit setting the loading to true, because componentWillMount in PokemonList component takes care of that.
    //const loading = true;

    // I've changed your species array, that way it should work as expected.
    const species = [
      {name: "bulbasaur"},
      {name: "ivysaur"},
      {name: "venusaur"}
    ];

    wrapper.setState({
      fetched,
      species
    });

    expect(toJson(wrapper)).toMatchSnapshot();
  });
});


我也建议在获取中使用https。

08-19 21:24