Typeorm 装饰器不是函数
Posted
技术标签:
【中文标题】Typeorm 装饰器不是函数【英文标题】:Typeorm decorator is not a function 【发布时间】:2020-07-29 20:55:46 【问题描述】:我有以下要测试的控制器:
class Album
public static getAlbums(): Promise<AlbumModel[]>
return getRepository(AlbumModel).find( relations: ['pictures'] );
它与模型相关联,我将 typeorm 与装饰器一起使用。这就是我使用 Jest 时的问题所在
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[];
为了测试这个控制器,我正在使用 ts-jest。这是我的单元测试:
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();
);
);
当我运行测试时,我收到以下错误:
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;
它有什么问题?
这是我的 package.json 的一部分
"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"
【问题讨论】:
【参考方案1】:你需要模拟出typeorm
,像这样:
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: () => ,
)
【讨论】:
如何将其添加到现有项目中?它自己的文件和导入的 .spec.ts 文件,还是完全其他的文件? 你只需要将它添加到测试文件中【参考方案2】:我喜欢尽可能多地留下 typeorm
自动模拟,所以我选择了不同的方法。我模拟所有typeorm
,然后只覆盖我正在使用的特定装饰器:
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())
然后,当我想模拟 .find()
之类的某些方法时,我模拟 EntityManager
的特定方法:
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',
);
【讨论】:
以上是关于Typeorm 装饰器不是函数的主要内容,如果未能解决你的问题,请参考以下文章