Tips on mocking a function using Jest

I'm currently working on testing a typescript class using Jest. Here is the class I am trying to test:

//MyClass.ts
import { foo } from './somewhere/FooFactory';
export class MyClass {
  private _state : number;
  constructor( arg : string ) {
    this._state = foo( arg );
  }

  public getState() : string {
    return this._state;
  }
}

Below is my current test setup:

//MyClass.spec.ts
import { MyClass } from './MyClass';
describe( 'test MyClass', () => {
  test( 'construct' => {
    const c = new MyClass( 'test' );
    expect( c ).toBeDefined();
    expect( c.getState() ).toEqual( 'TEST' );
  } );
} );

Any ideas on how I can mock the foo function used inside MyClass in order to make this test pass?

Answer №1

There are several approaches to tackle this issue.


You have the option to only mock foo using jest.spyOn in combination with mockImplementation:

import { MyClass } from './MyClass';
import * as FooFactory from './somewhere/FooFactory';

describe('test MyClass', () => {
  test('construct', () => {
    const mock = jest.spyOn(FooFactory, 'foo');  // spy on foo
    mock.mockImplementation((arg: string) => 'TEST');  // replace implementation

    const c = new MyClass('test');
    expect(c).toBeDefined();
    expect(c.getState()).toEqual('TEST');  // SUCCESS

    mock.mockRestore();  // restore original implementation
  });
});

Alternatively, you can automatically mock FooFactory using jest.mock, then set an implementation for foo:

import { MyClass } from './MyClass';
import * as FooFactory from './somewhere/FooFactory';

jest.mock('./somewhere/FooFactory');  // auto-mock FooFactory

describe('test MyClass', () => {
  test('construct', () => {
    const mockFooFactory = FooFactory as jest.Mocked<typeof FooFactory>;  // get correct type for mocked FooFactory
    mockFooFactory.foo.mockImplementation(() => 'TEST');  // provide implementation for foo

    const c = new MyClass('test');
    expect(c).toBeDefined();
    expect(c.getState()).toEqual('TEST');  // SUCCESS
  });
});

You also have the option to mock FooFactory by using a module factory passed to jest.mock:

import { MyClass } from './MyClass';

jest.mock('./somewhere/FooFactory', () => ({
  foo: () => 'TEST'
}));

describe('test MyClass', () => {
  test('construct', () => {
    const c = new MyClass('test');
    expect(c).toBeDefined();
    expect(c.getState()).toEqual('TEST');  // SUCCESS
  });
});

Lastly, if you intend to utilize the same mock in multiple test files you can mock the user module by creating a mock at

./somewhere/__mocks__/FooFactory.ts
:

export function foo(arg: string) {
  return 'TEST';
}

...then invoke

jest.mock('./somewhere/FooFactory');
to apply the mock in the test:

import { MyClass } from './MyClass';

jest.mock('./somewhere/FooFactory');  // use the mock

describe('test MyClass', () => {
  test('construct', () => {
    const c = new MyClass('test');
    expect(c).toBeDefined();
    expect(c.getState()).toEqual('TEST');  // SUCCESS
  });
});

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

Ways to incorporate forms.value .dirty into an if statement for an Angular reactive form

I'm a beginner with Angular and I'm working with reactive Angular forms. In my form, I have two password fields and I want to ensure that only one password is updated at a time. If someone tries to edit both Password1 and Password2 input fields s ...

Attempting to utilize a namespace-style import for calling or constructing purposes will result in a runtime failure

Using TypeScript 2.7.2 and VSCode version 1.21 with @types/express, I encountered an issue where in certain cases VSCode would report errors like: A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Interestingly ...

Angular 2/4 - Saving User Object Information in the Front-End Instead of Repeatedly Contacting the Back-End Server

Is there a more efficient way to store and update the current user details in the frontend, without constantly making new HTTP GET requests to the backend every time a new component loads? The solution I came up with is a UserService class that handles se ...

Tips for resolving Typescript type error when overriding MuiContainer classes

My application is divided into two main files: (https://codesandbox.io/s/react-ts-muicontainer-override-yywh2) //index.tsx import * as React from "react"; import { render } from "react-dom"; import { MuiThemeProvider } from "@material-ui/core/styles"; imp ...

Testing a function that triggers a click event and calls the history push method using jest-enzyme

Trying to test a component with a button that triggers a function, which takes a state from useState and navigates to a new route with a parameter inside. How can I effectively test this function? Encountering the following error: TypeError: history.push i ...

encountering an error of unsupported grant type while attempting to authenticate a user

I've seen a lot of discussions on this topic, but none have addressed my specific issue. Currently, I am working on an angular 5 application and trying to retrieve an authentication token by sending a post request to a server. Testing the connection ...

Error encountered: "Jest error - TypeError: Unable to access property 'preventDefault' because it is undefined."

I encountered an issue while testing the function below, resulting in the error mentioned above. function toggleRecovery = e => { e.preventDefault() this.setState( { recovery: !this.state.recovery }, () => { ...

The impact of redefining TypeScript constructor parameter properties when inheriting classes

Exploring the inner workings of TypeScript from a more theoretical perspective. Referencing this particular discussion and drawing from personal experiences, it appears that there are two distinct methods for handling constructor parameter properties when ...

Converting milliseconds into days, hours, minutes, and seconds using Angular

Currently, I am attempting to convert milliseconds to the format dd:hh:mm:ss. For example, given 206000 milliseconds. The desired format for this value would be: 00:00:03:26. However, when utilizing the following code: showTimeWithHour(milliSeconds: numb ...

lines stay unbroken in angular

I am encountering an issue when I execute the following code: DetailDisplayer(row) : String { let resultAsString = ""; console.log(row.metadata.questions.length); (row.metadata.questions.length != 0 )?resultAsString += "Questions ...

Challenges encountered while deploying a NextJS project with TypeScript on Vercel

Encountering an error on Vercel during the build deploy process. The error message says: https://i.stack.imgur.com/Wk0Rw.png Oddly, the command pnpm run build works smoothly on my PC. Both it and the linting work fine. Upon inspecting the code, I noticed ...

Using TypeScript to validate React Functional components

As I delve into TypeScript for a React app using next.js, I find myself grappling with how to properly type React components. One of my components looks like this... type Props = { children: JSX.Element; }; export default function SiteLayout({ children ...

Tips for updating an Angular renderer's value

I have a challenge with implementing a background color change when clicking on a th element. Currently, it works fine when I click on it, but I would like to make it so that if I click on another th element, the previous one will turn off. However, if I ...

how to verify if a variable exists in TypeScript

Is there a recommended method for verifying if a variable has a value in TypeScript 4.2? My variable may contain a boolean value. I'm thinking that using if(v){} won't suffice as the condition could be disregarded if it's set to false. ...

Tips on extracting the value from an observable and storing it in a variable

I am facing a challenge in returning a value from an observable method to assign it to a public variable for later use. Specifically, I need to retrieve this value and store it in the 'viewcount' variable for utilization in another function. pub ...

What are the proper methods for accurately testing vuex state and mutations?

Can someone guide me on how to properly test mutations and state? I have a modal window component that is rendered when the showModal property in the state is true. There is an event triggering a mutation that changes this property. How can I verify that a ...

What is the best way to iterate through an enum?

The type 'string' cannot be assigned to the type 'online' or 'offline'. I must be overlooking something, but I'm not sure what it is. enum StatusOptions { ONLINE = 'ONLINE', OFFLINE = 'OFFLINE', ...

What is the most appropriate form to use, and what factors should be considered in determining

Incorporating generics in typescript allows me to create a generic function in the following manner: Choice 1 declare function foo1<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } Alternatively, I have the option to omit the seco ...

having difficulties entering text into the react input field

At the moment, my input field defaults to 1, but when I try to type something in it, nothing happens. interface Orders { order_graph_1: number; order_graph_2: number; } interface MyProps extends Orders { setOrders: (...args: any) => void; / ...

Retrieving properties of a universal function

I am facing a challenge in creating a class that accepts a factory function as one of its parameters in the constructor, which is then used to create instances of another class. The implementation below is written in JavaScript. // item to create class Ite ...