Enhance your testing with jest-mock-extended: utilizing object input in Typescript mocks

I have incorporated jest-mock-extended into my testing routine.

The code snippet I aim to test is as follows:

class A {

  constructor(private b: B){}

  public test(x: string): string {

    const res1 = this.b.compose({
      name: x + '_foo'
    })

    const res2 = this.b.compose({
      name: x + '_bar'
    })
  }

  return res1 + '_' + res2
}

Here's my testing scenario:

test(() => {
  const bMock: MockProxy<B> = mock<B>()
  const a: A = new A(bMock)
  
  bMock.compose.calledWith({
                x: 'yoyo_foo'
            }).mockReturnValueOnce(x + '_once')

  bMock.compose.calledWith({
                x: 'yoyo_bar'
            }).mockReturnValueOnce(x + '_twice')
  //ACT
  const result = a.test('yoyo')

  //ASSERT
  expect(result).toBe('yoyo_foo_once_yoyo_bar_twice)
})

However, due to the use of calledWith function with referential equality, the behavior is not as expected and the mocked object's compose function returns undefined. Is there a way to rectify this issue? Perhaps by implementing shallow equality in some manner? I am looking for a solution that allows me to utilize the calledWith function with an object. Is such implementation possible? Alternatively, is there another approach to mocking the compose function based on its input parameters?

Answer №1

I recommend utilizing the containsValue('value') matcher from the jest-mock-extended library.

Ensure to implement this in your eg.ts file.

export interface B {
    compose(obj): string
}

export class A {
    constructor(private b: B) {}

    public test(x: string): string {
        const res1 = this.b.compose({
            name: x + "_foo"
        })

        const res2 = this.b.compose({
            name: x + "_bar"
        })
        return res1 + "_" + res2
    }
}

Also, make sure to include it in your eg.test.ts file for testing purposes.

// libs
import { test, expect } from "@jest/globals"
import { mock, MockProxy, objectContainsValue } from "jest-mock-extended"

import { A, B } from "./eg"

test("test", () => {
    const bMock: MockProxy<B> = mock<B>()
    const a: A = new A(bMock)

    bMock.compose
        .calledWith(objectContainsValue("yoyo_foo"))
        .mockReturnValueOnce("yoyo_foo" + "_once")

    bMock.compose
        .calledWith(objectContainsValue("yoyo_bar"))
        .mockReturnValueOnce("yoyo_bar" + "_twice")
    //ACT
    const result = a.test("yoyo")

    //ASSERT
    expect(result).toBe("yoyo_foo_once_yoyo_bar_twice")
})

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

What is the best way to assign a value to an option element for ordering purposes?

My select element is being populated with fruits from a database, using the following code: <select name="fruitsOption" id="fruitsOptionId" ngModel #fruitRef="ngModel"> <option *ngFor="let fruit of fruits">{{fruit}}</option> </selec ...

Creating a Custom Select Option Component with Ant Design Library

Is it possible to customize options in an antd select component? I have been trying to render checkboxes alongside each option, but I am only seeing the default options. Below are my 'CustomSelect' and 'CustomOption' components: // Cu ...

Testing asynchronous errors with Sequelize and Postgres

Recently, I've been working on writing unit tests for Sequelize with a Postgres database and using Jest for testing. While trying to get the following code to work: test('email field only takes valid emails', () => { expect.assertions( ...

Tips for simulating difficult private attributes within a class during unit testing in TypeScript

Is there a way to mock the value of a hard private property in a unit test? For example, how can I expect something like expect(event.getEventHis()).toBeEqual(['a', 'b']) export class EventController { #event: []; constructor() { ...

What is the best way to establish communication with the root component in Angular?

I have implemented a modal in the root component that can be triggered from anywhere. However, I am facing a dilemma on how the bottom component can communicate with the top component without excessive use of callback functions. Root Component <contai ...

Prevent users from submitting multiple times using Angular

There is an issue where users click the save button multiple times, causing a queue of requests to be submitted and resulting in the creation of duplicate data. How can we prevent this on the front-end so that only one request is submitted even if the butt ...

Save a cookie within the Figma desktop application by utilizing the Node.js API

I'm currently developing a figma plugin using typescript that includes a login module. I've set up the API using Node.js, but I'm encountering an issue with storing cookies. After checking the console in the Figma desktop app, I noticed tha ...

TypeScript is failing to identify a correctly typed property

Currently, I am facing issues while converting a Material UI Dashboard from React to Typescript. The problem arises during TypeScript compilation where the property in question meets the criteria mentioned in the error message. To put it briefly, the compi ...

Angular 7: An unexpected error occurred when trying to inject TripsMenu into MenuWidgetComponent in AppModule

Encountering an issue in angular 7, where I am trying to inject my MenuWidgetComponent in the home component. I have imported it in the widget component and exported it via index.ts. However, the following error persists: I searched online but couldn&apos ...

TypeScript Angular Forms: Implementing correct typing for dynamic form fields

I have a formgroup that looks like this: this.formBuilder.group<{ id: number; nameDe?: FormControl<string>; nameFr?: FormControl<string>; nameIt?: FormControl<string>; }>({ id: value?.id || null }); The main foc ...

Unlocking the secret to accessing keys from an unidentified data type in TypeScript

The code snippet above will not compile due to an error with the email protection link. const foo: unknown = {bar: 'baz'} if (foo && typeof foo === 'object' && 'bar' in foo) { console.log(foo.bar) } An erro ...

Sending optional data in Angular routesIn Angular, you can include additional

In my project utilizing angular 5, I have a lengthy routing file: const homeRoutes: Routes = [ { path: 'home', component: HomeComponent, children: [ { path: 'registration', component: RegistrationCompone ...

How can you create a function in typescript that only allows parameters of a specific type?

Here's what I'm trying to accomplish: function validateNumber(param: ???): param is number { } If the parameter can be a number, such as number | string or number | boolean, it should be accepted by the function. However, if the type is somethin ...

What is the process for assigning a value of a different type in blocking situations?

With Javascript, we have the flexibility to push values that we want to variables easily. However, in TypeScript, how can we block (throw an error) this action? let array: Array<string> = []; array.push(5); console.log(array); Even though my IDE no ...

Facing issues with module resolution while attempting to debug in VSCode

I'm currently in the process of debugging a module within our project. However, I've encountered difficulties attaching the debugger on Visual Studio Code since we recently changed the directory structure. Here is my tsconfig: { "compilerOptio ...

The Angular overlay panel remains open consistently

I recently developed an Angular component similar to p-overlaypanel, but I'm facing an issue where it remains open for every item I click. What I actually want is for only one overlay panel to be clicked and shown at a time - if I click on another ove ...

Trigger the Material UI DatePicker to open upon clicking the input field

I have a component that is not receiving the onClick event. I understand that I need to pass a prop with open as a boolean value, but I'm struggling to find a way to trigger it when clicking on MuiDatePicker. Here is an image to show where I want to ...

Safety in Choosing Typescript with "Name Safety"

I have a working code snippet that I'm currently using: export interface IReq { timestamp: number; }; export interface ITrack extends IReq { id: number; }; const track: Pick<ITrack, 'id'> = { id: 1 } While it's goo ...

The @Input property in the template is not successfully assigning a value to the input variable in Angular 5

Exploring some Angular 5 experiments with PrimeNG, I encountered challenges related to Angular 5. After creating a component with the following template: <p>Chemi-table works! And now, a message from our sponsors: {{this.nombre}}</p> <p-dat ...

Differences between a readonly variable and a method with a readonly type in TypeScript

Exploring the Contrast Between Readonly Variables and Readonly-Typed Methods in TypeScript Readonly Variable: maxLength: Readonly<Number | number | String | string> = 1; vs Readonly-Typed Method: maxLength(length: Number | number | String | stri ...