我有一个使用nestjs
with的项目typeorm
。
有一个database.config.ts
:
const entitiesPath = join(__dirname, '..', 'entities', '*.entity.{ts,js}');
const migrationsPath = join(__dirname, '..', 'migrations', '*.*');
const subscribersPath = join(__dirname, '..', 'subscribers', '*.subscriber.{ts,js}');
export const connectionConfig = {
name: 'default',
type: 'postgres',
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_DATABASE,
schema: process.env.DB_SCHEMA,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
};
export const databaseConfig = registerAs('database', () => ({
entities: [entitiesPath],
migrations: [migrationsPath],
subscribers: [subscribersPath],
...connectionConfig,
}));
database.module.ts
:
const connectionProvider = {
provide: DatabaseProvider.Connection,
useFactory: async (configService: ConfigService): Promise<Connection> => {
const databaseConfig = configService.get('database');
return await createConnection({
...databaseConfig,
});
},
inject: [ConfigService],
};
@Module({
imports: [
ConfigModule.forRoot({
load: [databaseConfig],
}),
],
providers: [connectionProvider, TestRepository],
exports: [connectionProvider, TestRepository],
})
export class DatabaseModule {}
TestRepository
是一个类,它扩展了BaseRepository
一个工作单元,几乎就像这里描述的那样。
连接是这样注入的:
constructor(@Inject(DatabaseProvider.Connection) private readonly conn: Connection) {
super(conn);
}
在基础存储库中,我QueryRunner
在构造函数中创建:
constructor(connection: Connection) {
super();
this.connection = connection;
this.unitOfWorkQueryRunner = this.connection.createQueryRunner();
}
现在,我想为工作单元编写一些集成测试,我得到了连接,TestRepository
就像这样:
describe('test.repository.ts', () => {
let app: INestApplication;
let connection: Connection;
let testRepository: TestRepository;
beforeAll(async () => {
app = await NestFactory.create(DatabaseModule);
connection = app.get<Connection>(DatabaseProvider.Connection);
});
beforeEach(async () => {
await connection.runMigrations();
testRepository = connection.getCustomRepository(TestRepository);
});
[...]
似乎testRepository
andconnection
被正确初始化了,this.unitOfWorkQueryRunner = this.connection.createQueryRunner()
我得到错误createQueryRunner
不是函数。
我究竟做错了什么?
编辑
connection
::
<ref *1> Connection {
migrations: [
CreateBrandTable1628717011030 {
name: 'CreateBrandTable1628717011030'
}
],
subscribers: [ GlobalSubscriber {} ],
entityMetadatas: [
EntityMetadata {
childEntityMetadatas: [],
inheritanceTree: [Array],
tableType: 'regular',
withoutRowid: false,
synchronize: true,
hasNonNullableRelations: false,
isJunction: false,
isAlwaysUsingConstructor: true,
isClosureJunction: false,
hasMultiplePrimaryKeys: false,
hasUUIDGeneratedColumns: true,
ownColumns: [Array],
columns: [Array],
ancestorColumns: [],
descendantColumns: [],
nonVirtualColumns: [Array],
ownerColumns: [],
inverseColumns: [],
generatedColumns: [Array],
primaryColumns: [Array],
ownRelations: [],
relations: [],
eagerRelations: [],
lazyRelations: [],
oneToOneRelations: [],
ownerOneToOneRelations: [],
oneToManyRelations: [],
manyToOneRelations: [],
manyToManyRelations: [],
ownerManyToManyRelations: [],
relationsWithJoinColumns: [],
relationIds: [],
relationCounts: [],
foreignKeys: [],
embeddeds: [],
allEmbeddeds: [],
ownIndices: [],
indices: [],
uniques: [],
ownUniques: [],
checks: [],
exclusions: [],
ownListeners: [],
listeners: [],
afterLoadListeners: [],
beforeInsertListeners: [],
afterInsertListeners: [],
beforeUpdateListeners: [],
afterUpdateListeners: [],
beforeRemoveListeners: [],
afterRemoveListeners: [],
connection: [Circular *1],
inheritancePattern: undefined,
treeType: undefined,
treeOptions: undefined,
parentClosureEntityMetadata: undefined,
tableMetadataArgs: [Object],
target: [class Brand extends CustomBaseEntity],
expression: undefined,
engine: undefined,
database: undefined,
schema: 'sh',
givenTableName: undefined,
targetName: 'Brand',
tableNameWithoutPrefix: 'brand',
tableName: 'brand',
name: 'Brand',
tablePath: 'sh.brand',
orderBy: undefined,
discriminatorValue: 'Brand',
treeParentRelation: undefined,
treeChildrenRelation: undefined,
createDateColumn: [ColumnMetadata],
updateDateColumn: undefined,
deleteDateColumn: undefined,
versionColumn: undefined,
discriminatorColumn: undefined,
treeLevelColumn: undefined,
nestedSetLeftColumn: undefined,
nestedSetRightColumn: undefined,
materializedPathColumn: undefined,
objectIdColumn: undefined,
propertiesMap: [Object]
}
],
name: 'default',
options: {
entities: [
...
],
migrations: [
...
],
subscribers: [
...
],
name: 'default',
type: 'postgres',
host: 'localhost',
port: '5432',
database: 'database_name',
schema: 'sh',
username: 'sh_user',
password: 'password'
},
logger: AdvancedConsoleLogger { options: undefined },
driver: PostgresDriver {
slaves: [],
connectedQueryRunners: [],
isReplicated: false,
treeSupport: true,
supportedDataTypes: [
'int',
'int2',
'int4',
'int8',
'smallint',
'integer',
'bigint',
'decimal',
'numeric',
'real',
'float',
'float4',
'float8',
'double precision',
'money',
'character varying',
'varchar',
'character',
'char',
'text',
'citext',
'hstore',
'bytea',
'bit',
'varbit',
'bit varying',
'timetz',
'timestamptz',
'timestamp',
'timestamp without time zone',
'timestamp with time zone',
'date',
'time',
'time without time zone',
'time with time zone',
'interval',
'bool',
'boolean',
'enum',
'point',
'line',
'lseg',
'box',
'path',
'polygon',
'circle',
'cidr',
'inet',
'macaddr',
'tsvector',
'tsquery',
'uuid',
'xml',
'json',
'jsonb',
'int4range',
'int8range',
'numrange',
'tsrange',
'tstzrange',
'daterange',
'geometry',
'geography',
'cube',
'ltree'
],
spatialTypes: [ 'geometry', 'geography' ],
withLengthColumnTypes: [
'character varying',
'varchar',
'character',
'char',
'bit',
'varbit',
'bit varying'
],
withPrecisionColumnTypes: [
'numeric',
'decimal',
'interval',
'time without time zone',
'time with time zone',
'timestamp without time zone',
'timestamp with time zone'
],
withScaleColumnTypes: [ 'numeric', 'decimal' ],
mappedDataTypes: {
createDate: 'timestamp',
createDateDefault: 'now()',
updateDate: 'timestamp',
updateDateDefault: 'now()',
deleteDate: 'timestamp',
deleteDateNullable: true,
version: 'int4',
treeLevel: 'int4',
migrationId: 'int4',
migrationName: 'varchar',
migrationTimestamp: 'int8',
cacheId: 'int4',
cacheIdentifier: 'varchar',
cacheTime: 'int8',
cacheDuration: 'int4',
cacheQuery: 'text',
cacheResult: 'text',
metadataType: 'varchar',
metadataDatabase: 'varchar',
metadataSchema: 'varchar',
metadataTable: 'varchar',
metadataName: 'varchar',
metadataValue: 'text'
},
dataTypeDefaults: {
character: [Object],
bit: [Object],
interval: [Object],
'time without time zone': [Object],
'time with time zone': [Object],
'timestamp without time zone': [Object],
'timestamp with time zone': [Object]
},
maxAliasLength: 63,
connection: [Circular *1],
options: {
entities: [Array],
migrations: [Array],
subscribers: [Array],
name: 'default',
type: 'postgres',
host: 'localhost',
port: '5432',
database: 'database_name',
schema: 'sh',
username: 'sh_user',
password: 'password'
},
postgres: PG {
defaults: [Object],
Client: [Function],
Query: [class Query extends EventEmitter],
Pool: [class BoundPool extends Pool],
_pools: [],
Connection: [class Connection extends EventEmitter],
types: [Object],
DatabaseError: [class DatabaseError extends Error]
},
database: 'competitor_monitoring_tool_test',
master: BoundPool {
_events: [Object: null prototype],
_eventsCount: 1,
_maxListeners: undefined,
options: [Object],
log: [Function (anonymous)],
Client: [Function],
Promise: [Function: Promise],
_clients: [Array],
_idle: [Array],
_pendingQueue: [],
_endCallback: undefined,
ending: false,
ended: false,
[Symbol(kCapture)]: false
}
},
manager: EntityManager {
repositories: [],
plainObjectToEntityTransformer: PlainObjectToNewEntityTransformer {},
connection: [Circular *1]
},
namingStrategy: DefaultNamingStrategy {
nestedSetColumnNames: { left: 'nsleft', right: 'nsright' },
materializedPathColumnName: 'mpath'
},
queryResultCache: undefined,
relationLoader: RelationLoader { connection: [Circular *1] },
isConnected: true
}
回购以重现类似问题(可能是相同的配置问题):https ://github.com/y-chen/nestjs-typeorm-undefined-issue