typescript - Typeorm dekoratörü bir fonksiyon değil


Test etmek istediğim aşağıdaki kontrolöre sahibim:

class Album {
  public static getAlbums(): Promise<AlbumModel[]> {
    return getRepository(AlbumModel).find({ relations: ['pictures'] });
  }
}

Bir modele bağlı olan, TypeORM'yi dekoratörlerle kullanıyorum. Jest kullandığımda sorun buradan kaynaklanıyor

import { Entity, PrimaryGeneratedColumn, Column, JoinTable, ManyToMany } from 'typeorm';
import { PicturesModel } from '../pictures/pictures.model';

@Entity({
  name: 'T_ALBUM_AL',
  synchronize: true,
})
export class AlbumModel {
  @PrimaryGeneratedColumn({
    name: 'AL_id',
  })
  id: number;

  @Column({
    name: 'AL_name',
  })
  name: string;

  @ManyToMany(() => PicturesModel, (picture: PicturesModel) => picture.id)
  @JoinTable({
    name: 'TJ_PICTURE_ALBUM_PA',
    joinColumn: {
      name: 'AL_id',
      referencedColumnName: 'id',
    },
    inverseJoinColumn: {
      name: 'PI_id',
      referencedColumnName: 'id',
    },
  })
  pictures: PicturesModel[];
}

Bu denetleyiciyi test etmek için ts-jest kullanıyorum. Bu benim birim testim :

import Album from './album.controller';

const getRepMock = jest.fn(() => ({
  find: jest.fn().mockImplementation(),
}));

jest.mock('typeorm', () => ({
  getRepository: getRepMock,
}));

describe('Album', () => {
  it('Should work', () => {
    Album.getAlbums();
    expect(getRepMock).toBeCalled();
  });
});

Testimi çalıştırdığımda, şu hatayı alıyorum:

 FAIL  src/api/v1/album/album.test.ts
  ● Test suite failed to run

    TypeError: typeorm_1.PrimaryGeneratedColumn is not a function

       6 | })
       7 | export class PicturesModel {
    >  8 |   @PrimaryGeneratedColumn({
         |    ^
       9 |     name: 'PI_id',
      10 |   })
      11 |   id: number;

Onunla ne yanlış?

Bu benim package.json dosyamın bir parçası

  "jest": {
    "preset": "ts-jest",
    "testEnvironment": "node",
    "coveragePathIgnorePatterns": [
      "/node_modules/"
    ]
  },
  "dependencies": {
    "@types/dotenv": "^8.2.0",
    "body-parser": "^1.19.0",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "express-boom": "^3.0.0",
    "glob": "^7.1.6",
    "morgan": "^1.10.0",
    "mysql": "^2.14.1",
    "pg": "^7.18.2",
    "reflect-metadata": "^0.1.10",
    "ts-jest": "^25.3.1",
    "typeorm": "0.2.24"
  },
  "devDependencies": {
    "@types/express": "^4.17.3",
    "@types/express-boom": "^3.0.0",
    "@types/glob": "^7.1.1",
    "@types/jest": "^25.2.1",
    "@types/morgan": "^1.9.0",
    "@types/node": "^8.0.29",
    "@types/supertest": "^2.0.8",
    "@typescript-eslint/eslint-plugin": "^2.24.0",
    "@typescript-eslint/parser": "^2.24.0",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.1.0",
    "eslint-import-resolver-alias": "^1.1.2",
    "eslint-plugin-import": "^2.20.1",
    "eslint-plugin-module-resolver": "^0.16.0",
    "jest": "^25.3.0",
    "nodemon": "^2.0.2",
    "supertest": "^4.0.2",
    "ts-node": "3.3.0",
    "typescript": "3.3.3333",
    "typescript-eslint": "^0.0.1-alpha.0"
  }

Cevap #1

Şunu yapmanız gerekiyor: typeorm'u şöyle taklit edin:

import { Repository, SelectQueryBuilder } from 'typeorm';
import { mock } from 'jest-mock-extended';

const repositoryMock = mock<Repository<any>>();
const qbuilderMock = mock<SelectQueryBuilder<any>>();

jest.mock('typeorm', () => {
    qbuilderMock.where.mockReturnThis();
    qbuilderMock.select.mockReturnThis();
    repositoryMock.createQueryBuilder.mockReturnValue(qbuilderMock);

    return {
        getRepository: () => repositoryMock,

        BaseEntity: class Mock {},
        ObjectType: () => {},
        Entity: () => {},
        InputType: () => {},
        Index: () => {},
        PrimaryGeneratedColumn: () => {},
        Column: () => {},
        CreateDateColumn: () => {},
        UpdateDateColumn: () => {},
        OneToMany: () => {},
        ManyToOne: () => {},
    }
})

Cevap #2

typeorm kadarını mümkün olduğunca otomatik olarak sahtelemeyi seviyorum, bu yüzden farklı bir yaklaşımı tercih ediyorum. typeorm'ün tamamını sahteleyip ardından sadece kullandığım belirli dekoratörleri geçersiz kılıyorum:

jest.mock('typeorm')
mocked(EntityRepository).mockImplementation(() => jest.fn())
mocked(Entity).mockImplementation(() => jest.fn())
mocked(Column).mockImplementation(() => jest.fn())
mocked(PrimaryGeneratedColumn).mockImplementation(() => jest.fn())
mocked(CreateDateColumn).mockImplementation(() => jest.fn())
mocked(UpdateDateColumn).mockImplementation(() => jest.fn())
mocked(DeleteDateColumn).mockImplementation(() => jest.fn())
mocked(OneToMany).mockImplementation(() => jest.fn())
mocked(ManyToOne).mockImplementation(() => jest.fn())
mocked(TableInheritance).mockImplementation(() => jest.fn())
mocked(ChildEntity).mockImplementation(() => jest.fn())

O zaman belirli yöntemleri, örneğin .find() yöntemini taklit etmek istediğimde, EntityManager'ın belirli yöntemlerini taklit ederim:

mocked(EntityManager.prototype.getCustomRepository).mockReturnValue(repository);
mocked(EntityManager.prototype.transaction as transactionOp).mockImplementation(async (runInTransaction) => runInTransaction(entityManager));
mocked(EntityManager.prototype.findOne).mockResolvedValue({
  id: 1,
  name: 'Cool Album',
});

İlgili makaleler