0

I'm doing some api fetching in my component. When doing unit testing, I'd like to mock the implementation of certain member functions:

//component.js
class Foo extends Component {
  prepareData() {
    getSthFromApi().then(getMoreFromApi).then(val=>this.setState({val}));
  }
  componentDidMount() {
    this.prepareData();
  }
}
//test.js
//What should this be?
Foo.prepareData = jest.fn().mockImplementation(() => {
  this.setState({val:1});
})
const comp = shallow(<Foo />);

How should I do it?

Firanolfind
  • 1,559
  • 2
  • 17
  • 36
Xun Yang
  • 4,209
  • 8
  • 39
  • 68

2 Answers2

1

You shouldn't mock your member function, instead you can mock getSthFromApi function and test both componentDidmount and prepareData together.

import { getSthFromApi } from "some-module";
jest.mock("some-module");

// in your test
getSthFromApi.resolves(1);
// here you can expect val to be 1 in your state.
Amit Chauhan
  • 6,151
  • 2
  • 24
  • 37
0

The problem with this code is that Foo.prepareData is static method, while prepareData is instance method.

Since prepareData is prototype method, it can be mocked on class prototype; this is one of the reasons why prototype methods are preferable:

jest
.spyOn(Foo.prototype, 'prepareData')
.mockImplementation(function () {
  this.setState({val:1});
});

Notice that mockImplementation should be provided with regular function because it doesn't need lexical this.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Do you mean I need to have `prepareData` as a prototype method for this code to work? – Xun Yang Jul 30 '18 at 09:13
  • prepareData is already prototype method in the code you've posted. This `class Foo extends Component { prepareData() {...} }` is prototype method. – Estus Flask Jul 30 '18 at 09:34