简体   繁体   中英

Is not a constructor error when trying to unit test Typescript classes

I am running into a TypeError: X is not a constructor when trying to test a simple FirestoreRepository class.

Full error:

TypeError: FirestoreRepository_1.FirestoreRepository is not a constructor
    at **new MasterService (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/src/Infrastructure/Services/MasterService.ts:28:38)**
    at Object.<anonymous> (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/src/index.ts:18:30)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Module.m._compile (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/ts-node/src/index.ts:1295:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Object.require.extensions.<computed> [as .ts] (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/ts-node/src/index.ts:1298:12)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/src/Infrastructure/Repositories/Database/FirestoreRepository.ts:2:1)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Module.m._compile (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/ts-node/src/index.ts:1295:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Object.require.extensions.<computed> [as .ts] (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/ts-node/src/index.ts:1298:12)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/tests/src/FirestoreImports.test.ts:6:1)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Module.m._compile (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/ts-node/src/index.ts:1295:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Object.require.extensions.<computed> [as .ts] (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/ts-node/src/index.ts:1298:12)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.implementationOfRequireOrImportForUnstableEsm [as requireOrImport] (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/mocha/lib/esm-utils.js:86:12)
    at Object.exports.loadFilesAsync (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/mocha/lib/esm-utils.js:73:34)
    at Mocha.loadFilesAsync (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/mocha/lib/mocha.js:467:19)
    at singleRun (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/mocha/lib/cli/run-helpers.js:125:15)
    at exports.runMocha (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/mocha/lib/cli/run-helpers.js:190:10)
    at Object.exports.handler (/Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/mocha/lib/cli/run.js:366:11)
    at /Users/kevansaba/Documents/Flutter projects/TRM/trm/Backend/node_modules/mocha/node_modules/yargs/build/index.cjs:443:71

This issue is possibly linked to import / export issues around CommonJS / ESM (as discussed here with Jest), but I am having a real hard time wrapping my head around why it might be the case.

As of now, I have the following Mocha / Chai setup:

package.json

"scripts": {
    "test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register 'tests/src/*.ts'"
  },

tsconfig.json

{
    "compilerOptions": {
      "target": "es2015",
      "lib": ["es6"],
      "module": "commonjs",
      "rootDir": ".",
      "outDir": "dist/",
      "esModuleInterop": true,
      "sourceMap": true,
      "moduleResolution": "node",
      "allowJs": true,
      "resolveJsonModule": true
    },
    "exclude": ["node_modules", "tests"],
    "include": ["src"]
}

FirestoreRepository.ts => my Firestore repo class:

import * as admin from 'firebase-admin';
import credentials from '../../../Config/keys/firebase_key';

export class FirestoreRepository implements IGameDataRepository {
    private db : FirebaseFirestore.Firestore;

    constructor(){
        this.db = FirestoreRepository.initializingFirestore();
    }

    static initializingFirestore(): FirebaseFirestore.Firestore {
        if (!admin.apps.length) {
            admin.initializeApp({
                credential: admin.credential.cert(credentials as admin.ServiceAccount)
            });
        }
        return admin.firestore();
    }

    async saveGame(someOptions):Promise<string | null>{
      // do stuff...
        
    }
}

My failing test:

import { expect } from 'chai';
import { test } from 'mocha';
import { FirestoreRepository } from '../../src/Infrastructure/Repositories/Database/FirestoreRepository';

test('Verify import of game parameters', async () => {
    const gameDataRepo = new FirestoreRepository();
    const paramName = 'stdParameters';
    const result = await gameDataRepo.saveGame('someRandomData');
    expect(result !== null && result !== undefined);
});

MasterServer.ts => a service where I use my FirestoreRepository...

import { FirestoreRepository } from "../Repositories/Database/FirestoreRepository";

export class MasterService {
    private _dbRepo: IGameDataRepository;

    public constructor(
        dbRepo?: IGameDataRepository
        ){
            this._dbRepo = dbRepo ?? new FirestoreRepository(); 
        }
}

index.ts

export const masterService = new MasterService();

I simplified, some of the examples provided, but so far I have understood that:

  1. imports of "simple" models in the tests seems to work well
  2. imports of my FirestoreRepository class cause issues which can be traced back to the index.ts file and MasterService.ts for reasons I cannot explain...

I may have found a simple workaround by simply importing the masterService in the test and using it to access its FirestoreRepository property. My tests work but I wonder if it's a recommended approach...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM