用Jest模拟axios调用后,状态不会更新

时间:2020-09-26 17:25:15

标签: reactjs unit-testing jestjs axios mocking

我正在尝试对进行axios调用并使用笑话和酶的结果更新状态的组件进行单元测试。但是,当我运行测试时,状态似乎没有更新,并且测试失败。

这是我正在测试的组件:

import React from 'react';
import axios from 'axios';
import Card from 'react-bootstrap/Card';

import CodeResults from './CodeResults.jsx';
import i18n from '../../../i18n.jsx';
import Loading from '../Loading.jsx';
import SearchBar from './SearchBar.jsx';

import '../../../../assets/css/CodeSearch.css';

/**
 * Provides a code search bar, handles searching the code text and displaying results
 * @state {Array} hits An array of search hits
 * @state {Boolean} loading A boolean that is true if the API call has not returned yet, false otherwise
 * @state {Boolean} requestFailed boolean that is true if the most recent API call returned an error,
 * false if there has been no previous API call, or if the most recent call did not return an error
 * @state {string} error Contains the message of an error if the API call returns an error 
 */
class CodeSearch extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            hits: [],
            loading: false,
            error: '',
        };
        this.search = this.search.bind(this);
        this.reactiveLoading = this.reactiveLoading.bind(this);
    }

    /**
     * Sends a call to the server to get hits for the given search phrase
     * @param {*} searchText the search phrase to find from repository
     */
    search(searchText) {
        if(!searchText || !searchText.trim()) return;
        const searchPhrase = searchText.trim();
        this.setState({ loading: true });
        axios.get(`/api/repos/${this.props.repository}/search/${searchPhrase}`).then((res) => {
            const response = res.data;
            this.setState({ hits: response.data.hits });
        }).catch((err) => {
            this.setState({ error: err.message });
        }).then(() => {
            this.setState({ loading: false});
        });
    }

    /**
     * Returns loading component if request has not returned, error alert if request
     * returns an error, result body otherwise
     */
    reactiveLoading() {
        if (this.state.loading) {
            return (
                <Loading />
            );
        }

        if (this.state.error) {
            return (
                <div className="text-center alert alert-danger w-50 m-auto" role="alert">
                    {this.state.error}
                </div>
            );
        }

        return(
            <CodeResults results={this.state.hits} />
        );
    }

    render() {
        return (
            <Card className='search'>
                <Card.Header>
                    <SearchBar callback={this.search} placeholder={i18n.t('Search.placeHolder')} />
                </Card.Header>
                <Card.Body>
                    {this.reactiveLoading()}
                </Card.Body>
            </Card>
        );
    }
}

export default CodeSearch;

这是测试以期望状态正确更新:

import Adapter from 'enzyme-adapter-react-16';
import axios from 'axios';
import React from 'react';
import { shallow, configure } from 'enzyme';

import CodeSearch from '../../main/components/Search/CodeSearch.jsx';

configure({ adapter: new Adapter() });

jest.mock('axios');

afterEach(() => {
    jest.clearAllMocks();
});

const dummyAxiosResponse = {
    data: {
        data: {
            hits: 
            [{
                branch: 'Branch Name 1',
                branchHits: [
                    {
                        file: 'File Name 1',
                        lines: [
                            {
                                num: 1,
                                content: ['if (', <mark key="codeMark0">true</mark>, ')']
                            },
                            {
                                num: 2,
                                content: ['{ return true; }']
                            },
                            {
                                num: 3,
                                content: ['let variable = ', <mark key="codeMark1">true</mark>, '']
                            },
                            {
                                num: 4,
                                content: ['let try = function(v) {']
                            },
                            {
                                num: 8,
                                content: ['for code in codes {']
                            },
                            {
                                num: 9,
                                content: ['\tprint ', <mark key="codeMark2">true</mark>, '']
                            },
                            {
                                num: 10,
                                content: ['}']
                            },
                        ],
                    },
                ],
            }],
        },
    },
};

describe('CodeSearch Component', () => {
    it('should update hits when search is called with non-empty input', async () => {
        axios.get.mockResolvedValue(() => Promise.resolve(dummyAxiosResponse));
        const codeSearchWrapper = shallow(<CodeSearch repository="testRepo" />);
        codeSearchWrapper.instance().search('true');
        expect(codeSearchWrapper.state('hits')).toEqual(dummyAxiosResponse.data.data.hits);
    });
});

运行测试时,测试失败,因为匹配的预期值和收到的值不匹配。期望值是虚拟axios响应中的hits数组,收到的值是一个空数组。我无法弄清楚为什么未使用正确的数据填充匹配。感谢您的任何帮助,谢谢!

0 个答案:

没有答案