Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

value must be a mock or spy function when using jest.fn

Getting this error

Matcher error: received value must be a mock or spy function

Received has type:  object
Received has value: {}

However, i think i shouldn't be getting this error because im using jest.fn. So im mocking the function.

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 (using the component in this file)

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>
        );
    };
};
like image 255
randal Avatar asked May 15 '19 18:05

randal


People also ask

How does Jest fn () work?

The jest. fn method allows us to create a new mock function directly. If you are mocking an object method, you can use jest.

How do you mock a value in Jest?

You can use jest. mock (line 4) to mock the lang dependency. In the example above, the mock module has a current field which is set to a mock function. You want to test both branches of hello, so you use mockReturnValueOnce to make the mock function return "GL" in the first invocation, and "EN" in the second one.

How do you write a spy function in Jest?

const spy = jest.spyOn(Class.prototype, "method") const spy = jest. spyOn(App. prototype, "myClickFn"); const instance = shallow(<App />);

What are mock functions in Jest?

Mock functions allow you to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls), capturing instances of constructor functions when instantiated with new , and allowing test-time configuration of return values.


2 Answers

I'm not 100% sure, but I believe you should do something like this:

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();
   });
});

You are testing if the onItemAdded function gets called when you click the <TodoAddItem /> component. So you have to mock it first using jest.fn and then check if the mocked function got called after you simulated the click.

like image 191
Diogo Capela Avatar answered Oct 07 '22 07:10

Diogo Capela


For me works replacing the next one:

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

With this one:

const setCategories = jest.fn();

I suppose that you should to set just jest.fn or jest.fn() in your code.

like image 23
anayarojo Avatar answered Oct 07 '22 07:10

anayarojo