Problems using NodeJS test runner in a NestJS project

566 Views Asked by At

I'm trying to run tests in my NestJS application using NodeJS native test runner, but I'm having some trouble.

1 - I can't run multiple test files with this script "test": "node -r tsconfig-paths/register -r ts-node/register --test ./test". It only works if I put the full path to a specific test file in the script, like "test": "node -r tsconfig-paths/register -r ts-node/register --test ./test/auth.test.ts", but this way I would have to create a script for each test file.

2 - I don't know why, but the "assert" object is undefined during the test. I saw people importing it as import assert from "node:assert" or import assert from "node:assert/strict", but if I try to import like this I get this error TypeError [Error]: Cannot read properties of undefined (reading 'strictEqual'). I had to import it as import { strict as assert } from "node:assert" and so it worked, but the other imports are way better.

This is my test code in case someone wants to see, but I still need to finish it.

import * as request from 'supertest';
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { AppModule } from '@src/app.module';
import { describe, before, after, it } from 'node:test';
import { strict as assert } from 'node:assert';
import { SignupDTO } from '@src/entities/user/user.type';

describe('Auth', () => {
  let app: INestApplication;

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

    app = moduleRef.createNestApplication();

    await app.init();
  });

  it('/POST signup', async () => {
    const body = new SignupDTO();

    body.name = 'Miguel O Hara';
    body.email = '[email protected]';
    body.password = 'spiderman2099';
    body.password_confirmation = 'spiderman2099';

    await request(app.getHttpServer())
      .post('/auth/signup')
      .send(body)
      .then((response)=>{
        assert.strictEqual(response.statusCode, 200);
      });
  });

  after(async () => {
    await app.close();
  });
});

If someone is working with node test runner and NestJS, I would really enjoy some tips. I just started using node native test runner instead of Jest, so I'm pretty new in this.

2

There are 2 best solutions below

0
Gabriel Borges On BEST ANSWER

Based on what Jay McDoniel did here, I created a file responsible for importing all the test files and run them.

In my test folder I have this:
enter image description here

In the run.ts file I have this:

import { join } from 'node:path';
import { readdir } from 'node:fs/promises';

const testFiles = [];
const testDir = join(__dirname);

(async () => {
  try {
    const files = await readdir(testDir);

    files.forEach(function (file) {
      if (file.match(/\.test\.ts$/)) {
        testFiles.push(import(join(testDir, file)));
      }
    });

    await Promise.all(testFiles);
  } catch (err) {
    console.log('Unable to scan directory: ' + err);
  }
})();

In the auth.test.ts file I just added export default before the describe function:

import * as request from 'supertest';
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import { AppModule } from '@src/app.module';
import { describe, before, after, it } from 'node:test';
import * as assert from 'node:assert/strict';
import { SignupDTO } from '@src/entities/user/user.type';

export default describe('Auth', () => {
  let app: INestApplication;

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

    app = moduleRef.createNestApplication();

    await app.init();
  });

  it('/POST signup', async () => {
    const body = new SignupDTO();

    body.name = 'Miguel O Hara';
    body.email = '[email protected]';
    body.password = 'spiderman2099';
    body.password_confirmation = 'spiderman2099';

    await request(app.getHttpServer())
      .post('/auth/signup')
      .send(body)
      .then((response)=>{
        assert.strictEqual(response.statusCode, 200);
      });
  });

  after(async () => {
    await app.close();
  });
});

And in my script I just put the path to run.ts file:

"test": "node -r tsconfig-paths/register -r ts-node/register --test ./test/run.ts"

Now, about the import for the assert object. While I was coding the run.ts file, I learned that I have to import the exact function that want, like I did for the join function from node:path, or I can just import everything as "something", like I did in my auth.test.ts file:

import * as assert from 'node:assert/strict';

Thanks for the idea, Jay. =)

1
Jay McDoniel On

What I did when trying out the node test runner, as it doesn't have glob support to run the tests in a single process, was I created an index.spec.ts file that imported my other tests. As for the assert import, I was using import assert = require('node:assert'), but I can't remember why that was the only option in the end.