nestjs how to disable ScheduleModule(@Cron) in tests
Asked Answered
N

3

8

This is my app.module.ts in NestJS:

import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';

@Module({
 imports: [CatsModule, ScheduleModule.forRoot()],
})
export class AppModule {}

And these are my tests beforeEach:

    const moduleRef = await Test.createTestingModule({
      imports: [AppModule],
    })
      .compile();

    app = moduleRef.createNestApplication();
    await app.init();

I want all @Cron() decorators to be disabled in tests. I want to disable ScheduleModule totally for tests.

How can it be done

(The reason is to avoid unexpected side effects in tests)

Nucleotidase answered 4/5, 2023 at 10:33 Comment(0)
L
0

I think the question is what are yo trying to test? If you're trying to test the code from the actual module you need to create a testing module simulating the actual AppModule configuration like so:

const moduleRef = await Test.createTestingModule({
      imports: [CatsModule, ScheduleModule],
    }).compile();

describe('your tests', ()=>{

})

I don't know if there's an specific use case you might want to test but normally you don't really need to start up your application to test the module, you just need to compile it and run the tests described. That's probably the reason why you have side effects, because you are actually running the app instead of testing it.

Lobar answered 10/7 at 0:0 Comment(0)
B
0

You can use mocks


export const mockTransactions: any = {
  runQuery: jest.fn(),
  runTransaction: jest.fn(),
  entityManager: jest.fn(),
}

export const mockEntityManager: any = {
  query: jest.fn(),
  createQueryBuilder: jest.fn(),
}

export const mockUser = {
  user_id: 2,
  first_name: null,
  last_name: null,
  email: '[email protected]',
  is_admin: true,
  last_login: '2024-04-04T05:39:19.002Z',
  is_active: true,
  created_on: new Date(),
  is_persist: null,
  alert_on_delivery_error: null,
  alert_on_order_expiration: null,
  login_ip: null,
  register_ip: null,
  registered_on: '2024-02-12T07:39:26.192Z',
  deleted: false,
  deleted_on: null,
  is_superuser: null,
  is_reseller: null,
  reseller_uuid: null
}

export const mockBullQueue: any = {
  add: jest.fn(),
  process: jest.fn(),
}

export const mockService = (name: string) => {
  return {
    provide: name,
    useValue: {
      create: jest.fn(),
      find: jest.fn(),
      findOne: jest.fn(),
      remove: jest.fn(),
      update: jest.fn(),
    }
  }
}

export const mockRepo = (name: string) => {
  return {
    provide: name,
    useValue: {
      create: jest.fn(),
      findAll: jest.fn(),
      findOneById: jest.fn(),
      findByCondition: jest.fn(),
      remove: jest.fn(),
      update: jest.fn(),
      findWithRelations: jest.fn(),
      deleteWhere: jest.fn(),
    }
  }
}

test example

import { SmsService } from './sms.service';
import { Test } from '@nestjs/testing';
import { getQueueToken } from '@nestjs/bull';
import { DataSource, EntityManager } from 'typeorm';
import { Transactions } from 'src/config/ormconfig';
import { JwtModule } from '../jwt/jwt.module';
import { mockBullQueue, mockEntityManager, mockRepo, mockService, mockTransactions } from '../../../test.helpers';

const mockUuid = '82d47dbf-e798-4674-ae43-b7e1e09125d3';
const mockSms = {
  uuid: '82d47dbf-e798-4674-ae43-b7e1e09125d3',
  to: '1232123223',
  from_id: '1234634221',
  created_on: new Date(),
  msg: 'string',
  file: null,
  code: 0,
  user_id: null,
  order_uuid: null,
  app_uuid: null,
  send_time: new Date(),
  delivered_on: null,
  user: null,
};


describe('Sms Service', () => {
  let smsService: SmsService;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      providers: [
        SmsService,
        {
          provide: 'SmsRepositoryInterface',
          useValue: {
            create: jest.fn().mockResolvedValue(mockSms),
            findAll: jest.fn().mockResolvedValue([mockSms, 1]),
            findOneById: jest.fn().mockResolvedValue(mockSms),
            findByCondition: jest.fn().mockResolvedValue(mockSms),
            remove: jest.fn(),
            update: jest.fn(),
            findWithRelations: jest.fn(),
            deleteWhere: jest.fn(),
          },
        },
        {
          provide: getQueueToken('job-queue'),
          useValue: mockBullQueue,
        },
        {
          provide: Transactions,
          useValue: mockTransactions,
        },
        {
          provide: EntityManager,
          useValue: mockEntityManager
        },
        {
          provide: DataSource,
          useValue: {
            options: {},
          },
        },
        mockService('OrderNumberServiceInterface'),
        mockRepo('OrderNumberRepositoryInterface'),
        mockService('UserServiceInterface')
      ],
      imports: [JwtModule],
    }).compile();

    smsService = moduleRef.get<SmsService>(SmsService);
  });

  it('Should be defined', () => {
    expect(smsService).toBeDefined();
  });
  it('SmsService.find()', async () => {
    const expectedOutput = [mockSms, 1];
    const result = await smsService.find({ uuid: mockUuid });
    expect(result).toEqual(expectedOutput);
  });

  it('SmsService.findOne()', async () => {
    const result = await smsService.findOne({ uuid: mockUuid });
    expect(result).toEqual(mockSms);
  });
});
Babble answered 11/7 at 4:55 Comment(0)
C
0

To disable the cron jobs in nestJS you need this:

function stopAllCronJobs(app: INestApplicationContext) {
    const schedulerRegistry = app.get(SchedulerRegistry);
    for (let cronName of schedulerRegistry.getCronJobs().keys()) {
        schedulerRegistry.deleteCronJob(cronName);
    }
}

const app: INestApplicationContext = await NestFactory.createApplicationContext(AppModule);
stopAllCronJobs(app);

The code is straightforward. You get the registry and delete every scheduled cron job. For the context app, play a little bit to get the correct reference. I use this script to disable cron in the console commands.

Columbia answered 18/9 at 8:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.