Having trouble getting Jest to manually mock in Nestjs?

When setting up a mock service like this:

// /catalogue/__mock__/catalogue.service.ts
export const CatalogueService = jest.fn().mockImplementation(() => {
  return {
    filterRulesFor: jest.fn().mockImplementation((role: Roles): Rule[] => rules.filter(r => r.roles.includes(role))
    fetchCountries: jest.fn().mockReturnValue(of(countriesStub())),
  }
});

In the upcoming structure:

/catalogue
  /__mock__
    catalogue.service.ts
  /tests
    catalogue.controller.spec.ts
  catalogue.module.ts
  catalogue.controller.ts
  catalogue.service.ts

The goal is to utilize the mock service within the catalogue.controller.spec.ts:

// /catalogue/tests/catalogue.controller.spec.ts
import { CatalogueController } from '../catalogue.controller';
import { CatalogueService } from '../catalogue.service';

jest.mock('../catalogue.service'); // <----- manual mocking here

describe('CatalogueController', () => {
  let controller: CatalogueController;
  let service: CatalogueService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [UtilsModule],
      controllers: [CatalogueController],
      providers: [CatalogueService],
    })
    .compile();

    controller = module.get<CatalogueController>(CatalogueController);
    service = module.get<CatalogueService>(CatalogueService);
    jest.clearAllMocks();
  });
}

However, encountering an issue when attempting to use it:

describe('getCountries', () => {
  let countries: Country[];
  beforeEach(async () => {
    service.fetchCountries()
    .subscribe(countries => console.log(countries)); // <----- here

    countries = await firstValueFrom(controller.getCountries());
  });

  it('should be called', () => {
    expect(service.fetchCountries).toBeCalledTimes(1);
  });

  it('should not be empty', () => {
    expect(countries.length).toBe(countriesStub().length);
  });
});

Getting a

TypeError: Cannot read property 'subscribe' of undefined
as though the mock service doesn't have the required functions defined.

If including the mock directly in the same file it works, but that's not the preferred approach:

let controller: CatalogueController;
let service: CatalogueService;

// vvvvv Mock service here vvvv
const mockCatalogueService = {
  filterRulesFor: jest.fn().mockImplementation((role: Roles): Rule[] => rules.filter(r => r.roles.includes(role))),
  fetchCountries: jest.fn().mockReturnValue(of(countriesStub())),
};

beforeEach(async () => {
  const module: TestingModule = await Test.createTestingModule({
    imports: [UtilsModule],
    controllers: [CatalogueController],
    providers: [CatalogueService],
  })
  .overrideProvider(CatalogueService) // <--- Implementing here
  .useValue(mockCatalogueService)     // <--- and here
  .compile();

  controller = module.get<CatalogueController>(CatalogueController);
  service = module.get<CatalogueService>(CatalogueService);
  jest.clearAllMocks();
});

Answer №1

In jest, manual mocking can be done using the import statement. However, Nestjs takes a different approach by implementing Dependency Injection (DJ). This means that certain objects like services and controllers are obtained from a container that holds all instance objects of the application. You can experiment with this method:

import { CatalogueService } from '../catalogue.service';

jest.mock('../catalogue.service');
//...
const module: TestingModule = await Test.createTestingModule({
  imports: [UtilsModule],
  controllers: [CatalogueController],
  providers: [CatalogueService],
})
.useMocker((token) => {
  switch (token) {
    case CatalogueService:
      return CatalogueService;
    // more mock objects can be added here
  }
})
.compile();

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

Unusual problem with accessing Object values in vscode using typescript

When attempting to write Object.values in TypeScript, I encounter a visual error (although it compiles without issues). https://example.com/image1.png I have tried searching online and restarting vscode, and here is my current tsconfig.json. https://exa ...

What is the reason for the lack of compatibility between the TypeScript compilerOptions settings 'noEmitOnError: true' and 'isolatedModules: false'?

Whenever I try to execute TypeScript with isolatedModules set as true and then false, I keep encountering this error message: tsconfig.json(5,9): error TS5053: Option 'noEmitOnError' cannot be specified with option 'isolatedModules'. ...

Checking the formik field with an array of objects through Yup for validation

Here is a snippet of the code I'm working on: https://codesandbox.io/s/busy-bose-4qhoh?file=/src/App.tsx I am currently in the process of creating a form that will accept an array of objects called Criterion, which are of a specific type: export inte ...

Utilizing a variable to pass props to a component (instead of a static component) within React Router 5

In react-router 5, you can pass props to a child component in this way: <Route path="/" exact render={ props => <MyPage title={myTitle} dataPath={myDataPath} {...props} />} /> However, I am using a route model in my ...

Unusual behavior of Typescript with Storybook's addon-docs

I'm trying to integrate storybook addon-docs into my TypeScript React project. Everything seems to be almost working, but I've noticed that the file name is affecting how the props type table gets rendered. Here is my file structure: src - Butto ...

"Is there a way to dynamically remap an array only when there are changes

One of the challenges I am facing is with a component called Page, which contains two components - Editor and Preview. Page has an array called items. [ { value: 0, text: 'Item 1' }, ... ] This array items is passed ...

What is the best way to emphasize specific months and years in an Angular Material datepicker?

I have an array of days, which can be from any year. I am attempting to customize the Angular Material datepicker to highlight specific months and years in the selection views based on the array of days. .html <input [matDatepicker]="picker" ...

Error encountered during conversion from JavaScript to TypeScript

I am currently in the process of converting JavaScript to TypeScript and I've encountered the following error: Type '(props: PropsWithChildren) => (any[] | ((e: any) => void))[]' is not assignable to type 'FC'. Type '(a ...

Creating a welcome screen that is displayed only the first time the app is opened

Within my application, I envisioned a startup/welcome page that users would encounter when the app is launched. They could then proceed by clicking a button to navigate to the login screen and continue using the app. Subsequently, each time the user revisi ...

Utilizing PrimeNg with Angular 2 to dynamically update charts using @ViewChild

I'm currently utilizing Angular2 with PrimeNG for my application. My dashboard includes charts and after attempting to upgrade to PrimeNG rc7 (from rc5) where they addressed an issue with updating charts, I'm facing challenges updating my chart d ...

The issue with the react-diagram stemmed from a conflict with @emotion/core

During the installation of react-diagrams by projectStorm, I encountered some errors which are shown in the following image: errorImg Despite attempting to downgrade the version of '@emotion/core' to ^10.0.0, the issue persisted. Here is a view ...

Zod vow denial: ZodError consistently delivers an empty array

My goal is to validate data received from the backend following a specific TypeScript structure. export interface Booking { locationId: string; bookingId: number; spotId: string; from: string; to: string; status: "pending" | "con ...

Using external URLs with added tracking parameters in Ionic 2

I am looking to create a unique http link to an external URL, extracted from my JSON data, within the detail pages of my app. Currently, I have the inappbrowser plugin installed that functions with a static URL directing to apple.com. However, I would lik ...

Encountering a hiccup while trying to install Svelte, Skeleton, and Tail

Recently entering the world of Svelte and TypeScript, I have encountered some unexpected errors after installation. Despite following the same steps as before, I am puzzled by what is causing these issues. This is the process I followed: npm create svelte ...

The upcoming development server will exclusively deliver HTML content without scripts or assets, mirroring the setup of the standard create-next-app template

In an attempt to recreate the problem I am facing, I decided to start by setting up a new Next.js app template folder using the command npx create-next-app (Version 13.1.6==latest, all default options, Node v18.14.0==LTS). However, when I try to run the pr ...

Issue: StaticInjectorError(DynamicTestModule)[CityService -> Http]: Http provider not found

I am working on a service that retrieves all cities from a web service. @Injectable() export class CityService { constructor(private http: Http, private router: Router, private auth: AuthService) { } public getAllCity(): Observable<City[]> { ...

The geolocation feature is operational in the browser test, but it is not functioning properly on the

I am currently creating an application that requires accessing the user's location at a specific point in time. To achieve this, I have utilized the ionic native geolocation feature which communicates with the Google API for reverse geocoding. Everyt ...

What steps can I take to fix the ESM / require error while using TypeScript 4.8?

My Node.js application uses TS 4.8, and I recently updated the file-type package. However, after the update, my project compilation fails with the following error: [1] const _fileType = /#PURE/ _interopRequireWildcard(require("file-type")); [1] ...

Chai expect() in Typescript to Validate a Specific Type

I've searched through previous posts for an answer, but haven't come across one yet. Here is my query: Currently, I am attempting to test the returned type of a property value in an Object instance using Chai's expect() method in Typescript ...

Incorporate an HTML span element with an onclick function bound in Angular framework

Is there a way to incorporate different icons by adding a span based on a flag, with an onclick event that triggers an internal function defined in the component ts? testfunc(){ console.log("it works") } flagToIcon(flag: boolean) { switch ( ...