Cezinha
Cezinha

Reputation: 31

Jest with fetch-mock generating error: TypeError: Cannot read property 'prototype' of undefined when using on nodejs

I'm almost sure it's my mistake, but I spent one entire day trying to solve and I've being failed 😞.

I'm trying to configure the fetch-mock on node to use with jest. I tried a lot of things and the best result that I have is this:

https://user-images.githubusercontent.com/824198/50566568-7b49e400-0d22-11e9-884f-89720899de3a.png

I'm sure my mock is working because if I pass it through parameter to the "Myclass.query" it works perfectly.

I'm also sure that the mock is arriving in my test file, because the mock function is present in the fetch module.

But... all together aren't working 😭.

I created a very simple and small project to see this problem happening:

https://github.com/cesarjr/test-node-fetch

Can anyone help me?

Upvotes: 3

Views: 4230

Answers (3)

MikeBeaton
MikeBeaton

Reputation: 3867

I had a similar issue where some Date functions were being mocked with jest.fn in order to avoid having today's date in each snapshot.

I guess - based on the answers above - that the mocked methods must have been used by jest itself before it was ready to mock them.

In my case, the mocks didn't actually need to be full jest mocks (i.e. jest.fn((...params...) => ...body...) ), just a plain mock function was sufficient (i.e. (...params...) => ...body... ), so changing this fixed it.

Upvotes: 0

wheresrhys
wheresrhys

Reputation: 23500

I've now found a reliable way to combine fetch-mock and jest http://www.wheresrhys.co.uk/fetch-mock/#usageusage-with-jest

Upvotes: 0

Brian Adams
Brian Adams

Reputation: 45780

Jest uses the mock at __mocks__/node-fetch.js any time node-fetch is required during the test.

The problem is that the first thing fetch-mock does is require node-fetch.

This means that Request is not defined when it is set on the config here, so calling prototype on the undefined Request causes an error here.

Someone smarter than me might know how to force Jest to require the actual node-fetch when fetch-mock requires node-fetch in the mock for node-fetch, but from what I can see it doesn't look like it is possible.


Looks like you will have to delete the mock at __mocks__/node-fetch.js and pass fetch to your code, something like this:

myclass.js

class MyClass {
  static query(fetch, sessionId, query) {
    const url = 'https://api.foobar.com';

    const body = {
      sessionId,
      query
    };

    return fetch(url, {
      method: 'post',
      body: JSON.stringify(body)
    })
      .then(res => res.json());
  }
}

module.exports = MyClass;

...then create the sandbox in your test and pass it to your code, something like this:

myclass.test.js

const fetch = require('fetch-mock').sandbox();
const MyClass = require('./myclass');

describe('MyClass', () => {
  describe('.query', () => {
    it('returns the response', () => {
      fetch.mock('*', {'result': {'fulfillment': {'speech': 'The answer'}}});

      expect.assertions(1);

      return MyClass.query(fetch, '123', 'the question').then((data) => {
        expect(data.result.fulfillment.speech).toBe('The answer');  // SUCCESS
      });
    });
  });
});

Upvotes: 1

Related Questions