node.jstypescriptnestjsnestjs-testingnode-test-runner

Problems using NodeJS test runner in a NestJS project


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 = 'spiderman2099@testmail.com';
    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.


Solution

  • 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 = 'spiderman2099@testmail.com';
        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. =)