【问题标题】:value must be a mock or spy function when using jest.fn使用 jest.fn 时 value 必须是 mock 或 spy 函数
【发布时间】:2019-10-02 22:52:29
【问题描述】:

收到此错误

匹配器错误:接收到的值必须是模拟或间谍函数

Received has type:  object
Received has value: {}

但是,我认为我不应该收到此错误,因为我使用的是 jest.fn。所以我在嘲笑这个功能。

describe('Should simulate button click', ()=> {
        it('should simulate button click', () => {
            // add the name of the prop, which in this case ites called onItemAdded prop,
            // then use jest.fn()
            const wrapper = shallow(<TodoAddItem onItemAdded={() => jest.fn()}/>)
            // console.log('props',wrapper.find('button').props());
            wrapper.find('button').simulate('click');

            expect(wrapper).toHaveBeenCalled(); // error happens when this executes
        })
    })

todo-add-item.js

import React, { Component } from 'react';

import './todo-add-item.css';

export default class TodoAddItem extends Component {

    render() {
        return (
            <div className="todo-add-item">

                <button 
                    className="test-button btn btn-outline-secondary float-left"
                    onClick={() => this.props.onItemAdded('Hello world')}>
                    Add Item
                </button>
            </div>
        );
    }
}

app.js(使用此文件中的组件)

import React, { Component } from 'react';

import AppHeader from '../app-header';
import SearchPanel from '../search-panel';
import TodoList from '../todo-list';
import ItemStatusFilter from '../item-status-filter';
import TodoAddItem from '../todo-add-item';

import './app.css';

export default class App extends Component {

    constructor() {
        super();

        this.createTodoItem = (label) => {
            return {
                label,
                important: false,
                done: false,
                id: this.maxId++
            }
        };

        this.maxId = 100;

        this.state = {
            todoData: [
                this.createTodoItem('Drink Coffee'),
                this.createTodoItem('Make Awesome App'),
                this.createTodoItem('Have a lunch')
            ]
        };

        this.deleteItem = (id) => {
            this.setState(({ todoData }) => {
                const idx = todoData.findIndex((el) => el.id === id);
                const newArray = [
                    ...todoData.slice(0, idx),
                    ...todoData.slice(idx + 1)
                ];

                return {
                    todoData: newArray
                };
            });
        };

        this.addItem = (text) => {
            const newItem = this.createTodoItem(text);

            this.setState(({ todoData }) => {
                const newArray = [
                    ...todoData,
                    newItem
                ];

                return {
                    todoData: newArray
                };
            });
        };

        this.onToggleImportant = (id) => {
            console.log('toggle important', id);
        };

        this.onToggleDone = (id) => {
            console.log('toggle done', id);
        };
    };

    render() {
        return (
            <div className="todo-app">
                <AppHeader toDo={ 1 } done={ 3 } />
                <div className="top-panel d-flex">
                    <SearchPanel />
                    <ItemStatusFilter />
                </div>
                <TodoList
                    todos={ this.state.todoData }
                    onDeleted={ this.deleteItem }
                    onToggleImportant={ this.onToggleImportant }
                    onToggleDone={ this.onToggleDone } />
                <TodoAddItem onItemAdded={ this.addItem } />
            </div>
        );
    };
};

【问题讨论】:

    标签: reactjs jestjs enzyme


    【解决方案1】:

    对我来说可以替换下一个:

    const setCategories = () => jest.fn();
    

    有了这个:

    const setCategories = jest.fn();
    

    我想您应该在代码中只设置jest.fn 或jest.fn()。

    【讨论】:

      【解决方案2】:

      我不是 100% 确定,但我相信你应该这样做:

      describe('should simulate button click', () => {
         it('should simulate button click', () => {
            const mockedFunction = jest.fn();
      
            const wrapper = shallow(<TodoAddItem onItemAdded={ mockedFunction } />);
      
            wrapper.find('button').simulate('click');
      
            expect(mockedFunction).toHaveBeenCalled();
         });
      });
      

      您正在测试单击&lt;TodoAddItem /&gt; 组件时是否调用了onItemAdded 函数。所以你必须先使用jest.fn 模拟它,然后检查模拟点击后是否调用了模拟函数。

      【讨论】:

      • 它通过了,太棒了。为什么您认为您的解决方案有效?
      • @randal 之所以有效,是因为 wrapper 是一个对象,而不是模拟函数本身。在将 mockedFunction 的引用传递给包装器时,您可以使用相同的 mockedFunction 常量来引用 jest.fn()。在这种情况下,两者都将指向 jest.fn() 因此您可以检查它是否已被调用。
      猜你喜欢
      • 2018-11-08
      • 2017-11-15
      • 1970-01-01
      • 2021-12-14
      • 2015-04-02
      • 2021-04-21
      • 2020-02-26
      • 1970-01-01
      • 2020-10-27
      相关资源
      最近更新 更多