【问题标题】:How to do unit tests with NodeJs (typescript) and Sequelize 5 (PostgreSQL)?如何使用 NodeJs (typescript) 和 Sequelize 5 (PostgreSQL) 进行单元测试?
【发布时间】:2023-04-11 10:33:02
【问题描述】:

我尝试使用 Sequelize 5 构建一个 api,但我不知道如何进行单元测试。我正在完成接口测试。但例如,在我的数据模型上,我不知道该怎么做。

我查看了“sequelize-test-helpers”npm 包,但我的数据模型以同样的方式未构建。所以..我需要修改我的代码架构还是你有解决方案?

我的位置数据模型接口:

export interface ICoordinates {
    type: string;
    coordinates: number[];
}

export default interface ILocation {
    id: string;
    coordinates: ICoordinates;
    description?: string | undefined | null;
    name: string;
    type_id: number;
    owner: string;
}

我的位置数据模型:

import { sequelize } from '../config/postgres';
import { Model, DataTypes } from 'sequelize';
import ILocation, { ICoordinates } from './interfaces/location.interface';

export class Location extends Model implements ILocation {
    public id!: string;
    public coordinates!: ICoordinates;
    public description: string | undefined | null;
    public name!: string;
    public type_id!: number;
    public owner!: string;
}

Location.init({
    id: { type: DataTypes.TEXT, primaryKey: true, allowNull: false},
    coordinates: { type: DataTypes.GEOMETRY('POINT', 4326), allowNull: false },
    description: { type: DataTypes.TEXT},
    name: { type: DataTypes.STRING, allowNull: false },
    type_id: { type: DataTypes.NUMBER, allowNull: false },
    owner: { type: DataTypes.TEXT, allowNull: false }
}, {
    tableName: "location",
    sequelize,
    timestamps: false
});

【问题讨论】:

    标签: node.js api unit-testing sequelize.js


    【解决方案1】:

    我将使用jestjs 作为测试框架。

    软件包版本:

    • "sequelize": "^5.21.3"
    • "jest": "^24.9.0"
    • "typescript": "^3.9.6"
    • "ts-jest": "^24.3.0"

    单元测试解决方案:

    interfaces.ts:

    export interface ICoordinates {
      type: string;
      coordinates: number[];
    }
    
    export default interface ILocation {
      id: string;
      coordinates: ICoordinates;
      description?: string | undefined | null;
      name: string;
      type_id: number;
      owner: string;
    }
    

    model.ts:

    import { sequelize } from '../../db';
    import { Model, DataTypes } from 'sequelize';
    import ILocation, { ICoordinates } from './interfaces';
    
    export class Location extends Model implements ILocation {
      public id!: string;
      public coordinates!: ICoordinates;
      public description: string | undefined | null;
      public name!: string;
      public type_id!: number;
      public owner!: string;
    }
    
    Location.init(
      {
        id: { type: DataTypes.TEXT, primaryKey: true, allowNull: false },
        coordinates: { type: DataTypes.GEOMETRY('POINT', 4326), allowNull: false },
        description: { type: DataTypes.TEXT },
        name: { type: DataTypes.STRING, allowNull: false },
        type_id: { type: DataTypes.NUMBER, allowNull: false },
        owner: { type: DataTypes.TEXT, allowNull: false },
      },
      {
        tableName: 'location',
        sequelize,
        timestamps: false,
      },
    );
    

    db.ts:

    import { Sequelize } from 'sequelize';
    import dotenv from 'dotenv';
    
    const dotenvConfigOutput = dotenv.config();
    if (dotenvConfigOutput.error) {
      console.error(dotenvConfigOutput.error);
      process.exit(1);
    }
    
    const envVars = dotenvConfigOutput.parsed!;
    console.log(envVars);
    
    const sequelize = new Sequelize({
      dialect: 'postgres',
      host: envVars.POSTGRES_HOST,
      username: envVars.POSTGRES_USER,
      password: envVars.POSTGRES_PASSWORD,
      database: envVars.POSTGRES_DB,
      port: Number.parseInt(envVars.POSTGRES_PORT, 10),
      define: {
        freezeTableName: true,
        timestamps: false,
      },
      pool: {
        max: 10,
        min: 0,
        idle: 10 * 1000,
      },
    });
    
    export { sequelize };
    

    model.test.ts:

    import { DataTypes } from 'sequelize';
    
    const mSequelize = {};
    
    jest.mock('../../db', () => {
      return { sequelize: mSequelize };
    });
    
    const modelStaticMethodMocks = {
      init: jest.fn(),
    };
    
    jest.mock('sequelize', () => {
      class MockModel {
        public static init(attributes, options) {
          modelStaticMethodMocks.init(attributes, options);
        }
      }
      return {
        ...jest.requireActual('sequelize'),
        Model: MockModel,
      };
    });
    
    describe('62584898', () => {
      it('should pass', async () => {
        await import('./model');
        expect(modelStaticMethodMocks.init).toBeCalledWith(
          {
            id: { type: DataTypes.TEXT, primaryKey: true, allowNull: false },
            coordinates: { type: DataTypes.GEOMETRY('POINT', 4326), allowNull: false },
            description: { type: DataTypes.TEXT },
            name: { type: DataTypes.STRING, allowNull: false },
            type_id: { type: DataTypes.NUMBER, allowNull: false },
            owner: { type: DataTypes.TEXT, allowNull: false },
          },
          {
            tableName: 'location',
            sequelize: mSequelize,
            timestamps: false,
          },
        );
      });
    });
    

    单元测试结果:

     PASS  src/examples/stackoverflow/62584898/model.test.ts
      62584898
        ✓ should pass (463ms)
    
    ----------|----------|----------|----------|----------|-------------------|
    File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ----------|----------|----------|----------|----------|-------------------|
    All files |      100 |      100 |      100 |      100 |                   |
     model.ts |      100 |      100 |      100 |      100 |                   |
    ----------|----------|----------|----------|----------|-------------------|
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        2.215s, estimated 5s
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-16
      • 2015-09-01
      • 2020-09-15
      • 2018-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      相关资源
      最近更新 更多