【发布时间】:2022-01-19 19:13:44
【问题描述】:
当前行为
我正在尝试应用 SOLID 原则,因此将我的服务与 TypeOrm 分离。
好处是我可以将InMemoryRepository 用于测试目的,将TypeOrmRepository 用于实际生产代码。
目前,我无法将自定义 TypeOrm 存储库作为任何随机提供程序注入。我怀疑处理@InjectRepository() 和TypeOrm 的特定行为会干扰这里。
然而,我可以毫无问题地将我的 In Memory 存储库注入到我的单元测试中。
[Nest] 12311 - 18/09/2021 à 06:22:43 [ExceptionHandler] Cannot read property 'save' of undefined
TypeError: Cannot read property 'save' of undefined
at TypeOrmWorkoutRepository.Object.<anonymous>.Repository.save (/Users/arthurmehmetoglu/Development/CorpoSano/back/src/repository/Repository.ts:150:29)
at WorkoutService.create (/Users/arthurmehmetoglu/Development/CorpoSano/back/src/workout/workout.service.ts:30:35)
at WorkoutResolver.create (/Users/arthurmehmetoglu/Development/CorpoSano/back/src/workout/workout.resolver.ts:22:32)
at /Users/arthurmehmetoglu/Development/CorpoSano/back/node_modules/@nestjs/core/helpers/external-context-creator.js:69:33
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at target (/Users/arthurmehmetoglu/Development/CorpoSano/back/node_modules/@nestjs/core/helpers/external-context-creator.js:76:28)
at /Users/arthurmehmetoglu/Development/CorpoSano/back/node_modules/@nestjs/core/helpers/external-proxy.js:9:24
[Nest] 12311 - 18/09/2021 à 06:22:43 [ExceptionHandler] Cannot read property 'findOne' of undefined +45ms
TypeError: Cannot read property 'findOne' of undefined
at TypeOrmWorkoutRepository.Object.<anonymous>.Repository.findOne (/Users/arthurmehmetoglu/Development/CorpoSano/back/src/repository/Repository.ts:370:29)
at TypeOrmWorkoutRepository.findById (/Users/arthurmehmetoglu/Development/CorpoSano/back/src/workout/repositories/typeorm-workout.repository.ts:12:17)
at WorkoutService.fillWorkoutWithExercises (/Users/arthurmehmetoglu/Development/CorpoSano/back/src/workout/workout.service.ts:38:50)
at WorkoutResolver.fillWorkoutWithExercises (/Users/arthurmehmetoglu/Development/CorpoSano/back/src/workout/workout.resolver.ts:32:32)
at /Users/arthurmehmetoglu/Development/CorpoSano/back/node_modules/@nestjs/core/helpers/external-context-creator.js:69:33
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at target (/Users/arthurmehmetoglu/Development/CorpoSano/back/node_modules/@nestjs/core/helpers/external-context-creator.js:76:28)
at /Users/arthurmehmetoglu/Development/CorpoSano/back/node_modules/@nestjs/core/helpers/external-proxy.js:9:24
更多详情请在下方输入代码。
输入代码
workout.module.ts
import ...
@Module({
imports: [TypeOrmModule.forFeature([Workout])],
providers: [
{
provide: EXERCISE_REPOSITORY,
useClass: TypeOrmExerciseRepository,
},
{
provide: WORKOUT_REPOSITORY,
useClass: TypeOrmWorkoutRepository,
},
WorkoutResolver,
WorkoutService,
],
})
export class WorkoutModule {}
workout.service.ts
...
@Injectable()
export class WorkoutService {
constructor(
@Inject(WORKOUT_REPOSITORY)
private readonly workoutRepository: WorkoutRepository,
@Inject(EXERCISE_REPOSITORY)
private readonly exerciseRepository: ExerciseRepository,
) {}
...
workout.service.spec.ts
...
describe('Workout Service', () => {
let workoutService: WorkoutService
let workoutRepository: WorkoutRepository
let exerciseRepository: ExerciseRepository
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: WORKOUT_REPOSITORY,
useClass: InMemoryWorkoutRepository,
},
{
provide: EXERCISE_REPOSITORY,
useClass: InMemoryExerciseRepository,
},
WorkoutService,
],
}).compile()
workoutService = module.get<WorkoutService>(WorkoutService)
workoutRepository = module.get<WorkoutRepository>(WORKOUT_REPOSITORY)
exerciseRepository = module.get<ExerciseRepository>(EXERCISE_REPOSITORY)
})
it('should be defined', () => {
expect(workoutService).toBeDefined()
})
...
workout-repository.interface.ts
import { Workout } from '../entities/workout.entity'
import { Exercise } from '../../exercise/entities/exercise.entity'
export const WORKOUT_REPOSITORY = 'WorkoutRepository'
export interface WorkoutRepository {
findById(id: string): Promise<Workout>
}
in-memory-exercise.repository.ts
export class InMemoryWorkoutRepository implements WorkoutRepository {
findById(id: string): Promise<Workout> {
return Promise.resolve(undefined)
}
}
typeorm-workout.repository.ts
@EntityRepository(Workout)
export class TypeOrmWorkoutRepository
extends Repository<Workout>
implements WorkoutRepository
{
async findById(workoutId: string): Promise<Workout> {
return this.findOne(workoutId)
}
}
环境
嵌套版本:7.6.0
对于工具问题:
- 节点版本:v14.16.1
- 平台:Mac
其他: 有关我正在努力实现的目标的更多详细信息,我的工作受到了这些文章的启发:
- https://jasonwhite.xyz/posts/2020/10/20/nestjs-dependency-injection-decoupling-services-with-interfaces
- https://khalilstemmler.com/articles/solid-principles/solid-typescript/#DIP
PS:我试图将代码简化为需要理解的内容。
【问题讨论】:
-
阅读有关使用 typeorm docs.nestjs.com/techniques/database 的文档可能会对您有所帮助
标签: typescript nestjs typeorm solid-principles in-memory-database