0

I am trying to mock functions from React Class component using Jest/Enzyme

Here is the source code

import React, { Fragment, Component } from "react";
import { withStyles } from "@material-ui/core/styles";
...

const useStyles = (theme) => ({
  // styles
});

class K8sIPCalculator extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: JSON.parse(JSON.stringify(initialState)),
    };
  }

  handleInputChange = (path, value) => {
    const newData = { ...this.state.data };
    newData[path] = value;
    this.setState({ data: newData });
  };

  calculate = (event) => {
    event.preventDefault();
    // does some calculation
    this.setState({ data: newData });
  };

  onReset = () => {
    this.setState({ data: JSON.parse(JSON.stringify(initialState)) });
  };

  render() {
    const { classes } = this.props;
    return (
      <Fragment>
        <form
          className={classes.formRoot}
          onSubmit={(event) => this.calculate(event)}
        >
              <InputLabel className={classes.label}>Nodes:</InputLabel>
              <TextField
                required
                size="small"
                type="number"
                InputProps={{
                  inputProps: {
                    min: 0,
                  },
                }}
                onChange={(e) =>
                  this.handleInputChange("nodes", e.target.value)
                }
                id="nodes-input"
                value={this.state.data.nodes}
              />
        </form>
      </Fragment>
    );
  }
}

export default withStyles(useStyles, { withTheme: true })(K8sIPCalculator);


I want to mock handleInputChange, onReset, calculate functions and check if it has been called or not and also it has been called with what arguments.

I have tried these methods.

const wrapper = mount(<K8sIPCalculator />);
const spy = jest.spyOn(wrapper, "handleInputChange");
Error: Cannot spy the handleInputChange property because it is not a function; undefined given instead
const spy = jest.spyOn(wrapper.instance(), "handleInputChange");
or wrapper.instance().handleInputChange = jest.fn();
Error: Cannot set property 'handleInputChange' of null
const spy = jest.spyOn(K8sIPCalculator.prototype, "handleInputChange");
Error: Cannot spyOn on a primitive value; undefined given
expect(spy).toHaveBeenCalled();
  • Don't mock parts of the thing you're supposed to be testing. Test the *behaviour* - does the rendered DOM reflect the expected outcome of the interactions? Then you can refactor within the component to your heart's content and be confident that it still works if the tests still pass, not have to edit all the tests just because you wanted to change an (internal!) method name. – jonrsharpe Feb 08 '21 at 12:43
  • Thank you for response, I just want to learn, why this is not working. As I am able to mock functions for other component using this structure ```wrapper.instance().handleInputChange = jest.fn()``` – Kishan Kumar Gupta Feb 08 '21 at 12:45
  • 1
    Because this is an instance of style wrapper, not your class. Check https://stackoverflow.com/a/53228623/3731501 – Estus Flask Feb 08 '21 at 13:19
  • @EstusFlask Thank you. I understood the issue. Can you also help me with the syntax? How can I access the class instance in Jest/Enzyme – Kishan Kumar Gupta Feb 08 '21 at 18:37
  • I cannot confirm if it's workable but I expect it to be here something like `let compRef = React.createRef(); let wrapper = mount(); jest.spyOn(compRef.current, 'handleInputChange') ...`. – Estus Flask Feb 08 '21 at 20:27

0 Answers0