Search code examples
unit-testingjestjs

Object { "json": [Function json], } error while mocking the global fetch


I am trying to mock the global fetch with a nested JSON response.

Mocking json() method is probably what went wrong but I can't figure it out.

// io_mockglobal.test.js

import {expect, jest} from '@jest/globals';
import {logMovies, logmovies1} from './io';

const data1={name:"test",salary:"123",age:"23"}

global.fetch = jest.fn((url,options) =>
  {  
    return new Promise((reject,resolve)=>{
    // if(typeof options.body!=='string')
    // {
    //   return reject("Not a string response")
    // }
      const res={
        json(){
          return new Promise((resolve)=>{
            resolve(data1)
          })
        }
      }
      resolve(res)
  })
})

test("Mock the global with stringyfy",async()=>{
  const l= await logmovies1(data1)
    console.log(l)
    //expect(l).toEqual({ "id": 423638});
    expect(l.status).toEqual('success');
})

// io.js

import path  from 'path';
import { promises as fs } from 'fs';

export async function logmovies1(data1){
  const response = await fetch("https://dummy.restapiexample.com/api/v1/create", {
    method: "POST", // or 'PUT'
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(data1),
  });
 
  const result = await response.json();
  console.log(result)
  return result
}

Solution

  • There is one mistake in your code, and I have some advice for you.

    You inverted resolve and reject:

    global.fetch = jest.fn((url, options) =>
      {  
        // return new Promise((reject, resolve) => {
        return new Promise((resolve, reject) => {
          const res = {
            json() {
              return new Promise((resolve) => {
                resolve(data1)
              })
            }
          }
          resolve(res)
      })
    })
    

    This should fix your issue.

    In JavaScript generally, when you resolve a value directly you can use Promise.resolve() instead of new Promise((resolve, reject) => {}).

    So you would have:

    global.fetch = jest.fn(async (url, options) => {
      return Promise.resolve({
        json: async () => Promise.resolve(data1),
      })
    })
    

    And with Jest, you can simplify this even more with jest.fn().mockResolvedValue(yourVariable).

    So the simplest version is:

    global.fetch = jest.fn().mockResolvedValue({
      json: jest.fn().mockResolvedValue(data1),
    })