Sling Academy
Home/Node.js/Fixing ‘done’ Callback Issue in NestJS Testing

Fixing ‘done’ Callback Issue in NestJS Testing

Last updated: December 31, 2023

When working on a Node.js project with NestJS, you might encounter an error related to test functions when they both take a ‘done’ callback. The error message indicates that your tests are not being constructed properly according to Jest, the testing framework commonly used with NestJS. This error arises from the fact that Jest expects tests to handle asynchronous code in a specific way, and using ‘done’ incorrectly can lead to conflicts in how tests are expected to conclude.

Understanding the ‘done’ Callback

In Jest, ‘done’ is a callback that can be used to handle asynchronous operations within tests. When passed to a test function, it tells Jest to wait for the ‘done’ to be called before considering the test as finished. However, NestJS has adopted more modern approaches, such as returning a Promise or using async/await syntax, which can cause incompatibilities when used in conjunction with the ‘done’ callback.

Sticking to Async/Await Syntax

To fix the mentioned error, one of the simplest approaches is to capitalize on JavaScript’s async/await syntax. This modern feature serves to handle asynchronous operations in a more readable and structured manner without the need for callbacks. When you define a test function as ‘async’, you can then use ‘await’ on any asynchronous operation, and Jest will know to wait for those operations to resolve before moving on to the next test.

describe('Cats Service', () => {
  let service: CatsService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [CatsService],
    }).compile();

    service = module.get(CatsService);
  });

  it('should return an array of cats', async () => {
    const result = ['test cat'];
    jest.spyOn(service, 'findAll').mockImplementation(async () => result);

    expect(await service.findAll()).toBe(result);
  });
});

Avoiding the Mixture of Done and Promises

If you prefer to stick with using ‘done’, you must make sure not to mix it with other asynchronous patterns like returning Promises or using async/await. In NestJS, if you start a test with an async function, any return of a Promise will be handled properly, but adding a ‘done’ parameter to it can confuse Jest and result in the very same error. If ‘done’ is your preferred method, ensure that you do not use async/await within the same test function.

describe('Cats Service', () => {
  let service: CatsService;

  beforeAll(done => {
    Test.createTestingModule({
      providers: [CatsService],
    }).compile()
    .then(module => {
      service = module.get(CatsService);
      done();
    });
  });

  it('should find a cat by id', done => {
    service.findById(1).then(cat => {
      expect(cat.name).toBe('Whiskers');
      done();
    });
  });
});

By following these practices and ensuring consistency in handling asynchronous code, you can avoid the error concerning the ‘done’ callback in NestJS tests. Whether you opt for the elegance of async/await or the directness of the ‘done’ callback, adapting to Jest’s expectations will result in successful and error-free test suites.

Next Article: Nest CLI Error: ‘nest’ Command Not Found in Node.js

Previous Article: NestJS: How to log stack trace of an error

Series: Nest.js Tutorials: From Basics to Advanced

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates