Unable to analyze parameters provided to a simulated object in Jest

I have a relatively simple Typescript class and method that I want to test using Jest. The goal is to mock out the dependencies of this method:

import {DynamoWorkflow} from '..';
import {Injectable} from '@nestjs/common';

@Injectable()
export class PipelineService {
    getCoverageByServiceName(serviceName: string): Promise<QueryResult<PipelineEvent>> {
        return new DynamoWorkflow().queryPipelineEvents(serviceName);
    }
}

In my testing process, I need to ensure that the argument passed to the .queryPipelineEvents() method matches my expectations. However, achieving this has proven to be challenging.

Below is my current test setup:

// setting up mock data...
const mockPipelineEvent: PipelineEvent = new PipelineEvent();
mockPipelineEvent.aut = "fake data";
const mockPipelineEvents: PipelineEvent[] = [mockPipelineEvent];
const mockQueryResult = {results: mockPipelineEvents, total: 1};

// creating a mocked dependency...
jest.mock('../../../../workflows/dynamoworkflow', () => {
  return {
    DynamoWorkflow: jest.fn().mockImplementation(() => {
      return {
        queryPipelineEvents: () => Promise.resolve(mockQueryResult),
      };
    })
  };
});

describe("PipelineService", () => {
  const mockDynamo = mocked(DynamoWorkflow, true);
    
  beforeEach(() => {
    mockDynamo.mockClear(); 
  })

  it("getCoverageByServiceName should return the same data as obtained from the database", () => {
    const methodArg = "foo-service";
    const serviceUnderTest = new PipelineService();
    const actualResult = serviceUnderTest.getCoverageByServiceName(methodArg);

    // Test #1: checking if the dependency was called
    expect(mockDynamo).toHaveBeenCalledTimes(1); //PASSES

    // Test #2: verifying if the correct argument was passed to the dependency method
    const mockedDynamoInstance = mockDynamo.mock.instances[0];
    const mockedDynamoMethod = mockedDynamoInstance.queryPipelineEvents;
    expect(mockedDynamoMethod.mock.calls[0][0]).toBe(methodArg);  

    // Test #3: confirming that the result matches our expectation
    expect(actualResult).resolves.toEqual(mockQueryResult); //PASSES
  });
})

The code above encounters a compilation issue with the error message:

Property 'mock' does not exist on type '(serviceName: string) => Promise<QueryResult<PipelineEvent>>'.ts(2339)
.

The problematic segment of code was referenced from Jest's official documentation.

I've attempted alternatives like

expect(mockDynamo.queryPipelineEvents).toBeCalledWith(methodArg);
, but faced another compilation error:
Property 'queryPipelineEvents' does not exist on type 'MockedObjectDeep<typeof DynamoWorkflow>'.ts(2339)

Another approach involved using

expect(mockDynamo.mock.instances[0].queryPipelineEvents).toBeCalledWith(methodArg);
, which compiled and executed successfully. However, it failed during execution with the following message:

    expect(received).toBeCalledWith(...expected)

    Matcher error: received value must be a mock or spy function

    Received has value: undefined

      44 |     // expect(mockedDynamoMethod.mock.calls[0][0]).toHaveBeenCalledWith(methodArg);
      45 |     // expect(mockDynamo.queryPipelineEvents).toBeCalledWith(methodArg);
    > 46 |     expect(mockDynamo.mock.instances[0].queryPipelineEvents).toBeCalledWith(methodArg);
         |                                                              ^
      47 | 
      48 |     // Test #3: confirm the result is what we expect
      49 |     expect(actualResult).resolves.toEqual(mockQueryResult);

If anyone can guide me on how to properly validate the arguments of a mocked method, your assistance would be greatly appreciated.

Answer №1

One of my colleagues was working on various tests and came across the solution for this problem. They discovered that assigning the mock method to the object and method being mocked was crucial. By eliminating all the previous mocking in the original code and replacing it with the following, they were able to achieve success:

jest.mock('../../../../workflows/dynamoworkflow');
const mockMethod = jest.fn();
mockMethod.mockReturnValue(Promise.resolve(mockQueryResult));
DynamoWorkflow.prototype.queryPipelineEvents = mockMethod; //<- important step!

Below is the updated and functional test case:

describe("PipelineService", () => {

  it("getCoverageByServiceName returns same data as db supplies", () => {
    // preparing mock data...
    const mockPipelineEvent: PipelineEvent = new PipelineEvent();
    mockPipelineEvent.aut = "fake data";
    const mockPipelineEvents: PipelineEvent[] = [mockPipelineEvent];
    const mockQueryResult = {results: mockPipelineEvents, total: 1};

    // setting up the mock...
    jest.mock('../../../../workflows/dynamoworkflow');
    const mockMethod = jest.fn();
    mockMethod.mockReturnValue(Promise.resolve(mockQueryResult));
    DynamoWorkflow.prototype.queryPipelineEvents = mockMethod;

    // calling the method we're testing...
    const methodArg = "foo-service";
    const serviceUnderTest = new PipelineService();
    const actualResult = serviceUnderTest.getCoverageByServiceName(methodArg);

    // performing the test...
    expect(mockMethod).toHaveBeenCalledWith(methodArg);
    expect(actualResult).resolves.toEqual(mockQueryResult);
  });

})

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 method to adjust the width of the PrimeNG ConfirmDialog widget from a logic perspective

Currently utilizing "primeng": "^11.2.0" and implementing the ConfirmDialog code below this.confirm.confirm({ header: 'Announcement', message: this.userCompany.announcement.promptMsg, acceptLabel: this.userCompany.announcement ...

Implementing Formik in React for automatic updates to a Material-UI TextField when blurred

Presently, I am developing a dynamic table where users can simultaneously modify multiple user details in bulk (Refer to the Image). The implementation involves utilizing Material-UI's <TextField/> component along with Formik for managing form s ...

Exploring FileReader in conjunction with React and Typescript

I am facing an issue while trying to upload a JSON file using an input element of type file. When I attempt to use the onload method on FileReader in TypeScript, I receive an error message saying "Cannot invoke an object which is possibly 'null'. ...

Is mocking all dependencies in an AngularJS controller necessary for unit testing?

Is it necessary to mock all the dependencies of my controller in order to test the scope? Here is a snippet of my code... .controller('SignupCtrl', ['$scope', 'vcRecaptchaService', '$http', '$location', & ...

What are the steps to generate an npm package along with definition files?

Is it possible to create an NPM package with definition files containing only interfaces declared in *.ts files? Consider a scenario where we have two interfaces and one class definition: export interface A { id: number; } export interface B { name: s ...

What is the reason Nav cannot be directly used in the constructor instead of using @ViewChild(Nav) nav: Nav in Ionic?

As a newcomer to Ionic, I am trying to understand the code snippet provided. My confusion lies in the purpose of "NAV" and why it is used in @viewchild(). While I can access the MenuController by using it in the constructor, I am unable to use NAV in the s ...

What is the purpose of using the `is` keyword in typescript?

Recently, I stumbled upon this code snippet: export function foo(arg: string): arg is MyType { return ... } Despite searching through documentation and Google, I couldn't find information on the is keyword. It's a widely used word that appe ...

Angular - Cannot assign operator function of type 'OperatorFunction<IUser, void>' to parameter of type 'OperatorFunction<Object, void>'

While working on adding a user login feature in Angular-13, I have the following model: export interface IUser { email: string; token: string; } Service: export class AccountService { baseUrl = environment.apiUrl; private currentUserSource = new ...

Removing HTML Tags in Ionic - A How-To Guide

After utilizing Ionic 3 to retrieve data from a WordPress API, I am encountering an issue with displaying the content on the app UI. The problem arises from the presence of HTML tags within the content being printed along with the text. While seeking solut ...

Checking the functionality of a feature with Jasmine framework in an Angular application

I am working on writing unit test cases and achieving code coverage for the code snippet below. Any advice on how to proceed? itemClick($event: any) { for (let obj of this.tocFiles) { let results = this.getchildren(obj, label); if (results) { conso ...

The property 'options' is not found in the type of union type

In my development project, I have defined a couple of interface types and a union type: export interface FieldOptions { value: string | number; viewValue: string; } export interface BaseField { id: string; derived?: boolean; required?: boolean; ...

What steps are required to utilize NgbSortableHeader for sorting a bootstrap table through programming?

I have a bootstrap HTML table (operated by ng-bootstrap for Angular and utilized NgbdSortableHeader to arrange table columns by clicking on the column). When I click on an element, it sorts the column in ascending, descending, or ''(none) order. ...

What is the method to verify that an Action was sent from one Action to another in NGXS?

I've been utilizing NGXS extensively throughout an application, but there are certain tasks that I still struggle to accomplish in a satisfactory manner. The documentation and other questions on this topic haven't provided the answers I seek. One ...

Creating an endless scrolling feature with Ionic 3

My tech stack includes symfony3 and FosRestBundle for the backend, and Ionic 3 for the frontend development. While attempting to implement an InfiniteScroll feature following the Ionic documentation, I encountered an issue where only the loading text and ...

What is the method to verify if an object contains a specific property or object in TypeScript?

When I try to verify if (!window.MSStream) ... I encounter an error in TypeScript, the intellisense highlights the MSStream object because it has not been declared - which is precisely why I need to check it. Unfortunately, this prevents me from building ...

Tips for showing nested JSON data in a PrimeNG table within Angular version 7

I am struggling to display nested json data in a PrimeNG table. When I retrieve the data using an HTTP service, it appears as [object][object] when displayed directly in the table. What I want is to show the nested json data with keys and values separated ...

Emphasize x-axis heading in a Highcharts graph

In my Highcharts bar graph, I am looking for a way to dynamically highlight the x-axis label of a specific bar based on an external event trigger. This event is not a standard click interaction within the Highcharts graph. Currently, I have been able to r ...

Is it possible to display properties and methods in Typescript without having to explicitly cast to a class type?

In an attempt to replicate a project issue, I crafted this piece of TypeScript code. The scenario involves having a base class (referred to as "Foo") and multiple other classes that extend from it. The goal of the "instanciateFoos" function is to create ...

Disadvantages of utilizing subjects as observables

Do you ever question the necessity of using the "asObserveable()" method on a subject? In my opinion, it seems to result in significant unnecessary overhead. The restrictions on methods like "next()" or "complete()" appear pointless to me. Is there a com ...

Verify characteristics of recursive object within Angular 7

I have an object similar to the one in the stackblitz linked below and I need to determine if a key is of type Date. If it is, I want to add 3 days to that date. I have successfully implemented this for non-recursive objects, but I am facing challenges wit ...