How can I confirm that node-fetch is being invoked during a TypeScript unit test?

Hey there! I have a module that exports some methods and I want to test them with unit tests. My project is built on typescript ^3.9.7 and has jest ^26.1.0 and ts-jest ^26.2.0 installed.

One of the methods in question requires node-fetch ^2.6.0 to utilize window.fetch in a node environment.

import fetch from 'node-fetch'

export const fetchResponseFromRemoteFile = (
  remoteFileUrl: string
): Promise<Response> =>
  fetch(remoteFileUrl)
    .then(res => {
      return res.status === 200
        ? res
        : new Error(`failed to retrieve ${remoteFileUrl}`)
    })
    .catch(e => e)

In one of my tests, I aim to verify that fetchResponseFromRemoteFile invokes fetch.

Approach 1

import { mocked } from 'ts-jest/utils'
import fetch from 'node-fetch'

jest.mock('node-fetch')

it('fetches', async () => {  
  const expectedResponse = { a: 1 }
  mocked(fetch).mockImplementation( () => <any>expectedResponse)
  ...
})


// mocked(fetch).mockImplementation( () => <any>expectedResponse)

TypeError: (0 , _utils2.mocked)(...).mockImplementation is not a function

Approach 2

it('fetches', async () => {
  const expectedResponse = { a: 1 }
  ;(fetch as jest.Mock).mockReturnValue(Promise.resolve(new Response(expectedResponse)))
  const remoteFile = await utils.fetchResponseFromRemoteFile(mockUrl)
  expect(fetch).toHaveBeenCalledTimes(1)
  expect(remoteFile.status).toEqual(200);
  expect(remoteFile.body).toEqual(expectedResponse);
  ...
})


// ;(fetch as jest.Mock).mockReturnValue(Promise.resolve(new Response(expectedResponse)))

ReferenceError: Response is not defined

Approach 3

import fetch from 'node-fetch'

jest.mock('node-fetch', () => jest.fn())

it('fetches', async () => {
  const expectedResponse = { body: { a: 1 } }
  const response = Promise.resolve(expectedResponse)
  fetch.mockImplementation(()=> response)
  ...
})


// fetch.mockImplementation(()=> response)

TypeError: _nodeFetch.default.mockImplementation is not a function

Any ideas on what could be causing these issues?

Thanks in advance!

Answer №1

When creating unit tests for this functionality, it is important to implement dependency injection:

export class FetchService {

  constructor(private readonly fetchInstance: any) {}

  public fetchResponseFromRemoteFile(
    remoteFileUrl: string
  ): Promise < Response > {
    this.fetchInstance(remoteFileUrl)
        .then(res => {
            return res.status === 200
                ? res
                : new Error(`failed to retrieve ${remoteFileUrl}`)
        })
        .catch(e => e);
  }
}

This allows you to create a mock object and inject it into your service during testing, like so:

const fetchMock = jest.Mock(); // Actual code may vary
const fetchService = new FetchService(fetchMock);

// Now you can perform assertions on the 'fetchMock'.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Text at the center of a series of circles on canvas

Can someone assist me in aligning my text at the center of 5 concentric circles? Below is the code I have written, but it doesn't seem to be working. Any suggestions on what modifications I need to make to achieve this would be greatly appreciated. Th ...

Implement Material UI Card Component in your React Project

I'm currently working on a project that includes a page with expandable cards arranged in a list format. The code I have right now is not very scalable, as I keep adding individual card tags for each item. What I would like to achieve is to load data ...

Modify object rotation animation direction using keyboard controls in Three.js

Adjusting the object rotation direction with key controls is within my capability by utilizing the following code: case 37: scene.rotation.x -= 0.01; break case 38: scene.rotation.z -= 0.01 break Nevertheless, the rotation remai ...

Saving the link to the search results for future reference

Procedure: onSearch(searchString) { if (this.props.history) { this.props.history.push( "/details?search=" + encodeURIComponent(searchString) ); } } Explore Bar: <Search onKeyPress={(event) => ...

Ajax modal login feature refuses to close

Struggling to close a modal login box? Everything seems to be functioning correctly with the modal screen and ajax features, but I'm facing issues when it comes to closing the modal form. The code snippet looks like this: HTML: <a href="#" cla ...

Receiving a blank array upon calling res.json() in Node.js script

I'm facing an issue with my code snippet that displays all posts, including the username and display picture of each user. Everything seems to be working fine as the log output is perfect. However, I'm struggling to return this data as a JSON obj ...

How do I convert the ImagePicker type to Base64 in Ionic Capacitor?

I am currently developing an app using Ionic (Angular-based) along with Capacitor Plugins, specifically the Camera Plugin. The main feature I am working on involves allowing users to choose up to 5 images from their gallery. To accomplish this, I have impl ...

Listen for the load event during an AJAX request without using jQuery's add

I have four HTML files and four corresponding JavaScript files. Each JavaScript file is externally loaded by its respective HTML file. Specifically, index.html loads javascript.js, 1.html loads javascript1.js, 2.html loads javascript2.js, and 3.html loads ...

How can VueJs effectively update the data fetched using the created function?

When working with the Promise Object, I prefer to utilize the "then" and "catch" functions instead of asynchronous functions for handling responses in a simpler way. This allows me to avoid using await and conditional if-else statements to check the stat ...

What is the recommended TypeScript type for setting React children?

My current layout is as follows: export default function Layout(children:any) { return ( <div className={`${styles.FixedBody} bg-gray-200`}> <main className={styles.FixedMain}> <LoginButton /> { children } ...

Ineffectiveness of Three.js camera's lookat function

I've been trying to modify the camera's focus point using a Vector3, but for some reason, the camera keeps looking at the scene's origin. I'm a bit perplexed as to why this is happening, especially since all the examples I've come ...

Ways to resolve the Error: object is not acceptable as a React child

I've recently started learning React and decided to work on a project that involves fetching random numbers with interesting facts from an API called "Numbers API." Unfortunately, I've encountered an error while running the code: "Error: ...

css background is repeating after the height of the div is reset

I'm working on a project where I want to resize an image while maintaining its aspect ratio to fit the height/width of the browser window. However, every time the code for resizing is implemented, the div height continues to increase with each resize ...

Tips for tracking advertisement views and saving them in a database

We recently placed our website advertisement on 2 different websites and are interested in tracking the number of clicks or hits we receive from those ads. We would like to store this data in our database. Can anyone suggest a method for accomplishing th ...

How to efficiently switch between classes in Ember Octane using Handlebars?

What is the best way to toggle between displaying a class on and off using Ember.js Octane? Should I use an @action or @tracked in this case? <img src="flower.jpg" alt="flower" class="display-on"> or <img src="flower.jpg" alt="flower" class=" ...

Tips for implementing React-Email & Resend feature using Firebase Cloud Functions

I am working on a Next.js application that combines React-Email, Resend, and Firebase Cloud Functions. The structure of the directories is as follows: https://i.sstatic.net/v8RUR5co.png My goal is to send an email to a user every time a document is creat ...

Obtaining the data stored in objects within a parse database

I'm currently facing an issue where I am trying to retrieve the name of the creator from the session object, which is a pointer. For testing purposes, I have been attempting to access this information but it keeps showing up as undefined. Any suggesti ...

How to Show Firestore Query Results in a React Native App

I'm struggling to correctly manage the synchronization, asynchronization, and promises related to querying Firestore. Let me simplify my scenario for you. I have different categories of items and I want to display all the categories along with their r ...

Angular JS causing text alignment issues in table cells when viewed on mobile devices

I have created a web application that requires both desktop and mobile views, utilizing Angular JS. Everything is functioning as expected except for the text alignment within tables. I attempted using <td align="left">, but it did not produce any cha ...

Avoid using window.location.href within an AJAX call in Laravel 5.2

My issue arises when I use Ajax in Laravel. The code runs and I am able to fetch the result, but a particular section does not execute: window.location.href = "http://stackoverflow.com"; $('.promotion').click(function(){ var id= ...