如何开玩笑模拟nestjs导入?

时间:2020-02-12 09:55:01

标签: node.js typescript unit-testing jestjs nestjs

我想为我的nestjs“课程”存储库服务(一种依赖于Mongoose Model和Redis的服务)编写单元测试。

courses.repository.ts:

    import { Injectable, HttpException, NotFoundException } from "@nestjs/common";
    import { InjectModel } from "@nestjs/mongoose"
    import { Course } from "../../../../shared/course";
    import { Model } from "mongoose";
    import { RedisService } from 'nestjs-redis';


    @Injectable({}) 
    export class CoursesRepository {

      private redisClient;
      constructor(
        @InjectModel('Course') private courseModel: Model<Course>,
        private readonly redisService: RedisService,
      ) {
        this.redisClient = this.redisService.getClient();

      }


      async findAll(): Promise<Course[]> {
        const courses = await this.redisClient.get('allCourses');
        if (!courses) {
          console.log('return from DB');
          const mongoCourses = await this.courseModel.find();
          await this.redisClient.set('allCourses', JSON.stringify(mongoCourses), 'EX', 20);
          return mongoCourses;
        }

        console.log('return from cache');
        return JSON.parse(courses);
      }
}

以这种方式初始化测试:

beforeEach(async () => {
  const moduleRef = await Test.createTestingModule({
    imports: [
      MongooseModule.forRoot(MONGO_CONNECTION,  { 
        useNewUrlParser: true,
        useUnifiedTopology: true
      }),
      MongooseModule.forFeature([
        { name: "Course", schema: CoursesSchema },
        { name: "Lesson", schema: LessonsSchema }
      ]),
      RedisModule.register({})
    ],
      controllers: [CoursesController, LessonsController],
      providers: [
         CoursesRepository,
         LessonsRepository
        ],
    }).compile();

  coursesRepository = moduleRef.get<CoursesRepository>(CoursesRepository);
  redisClient = moduleRef.get<RedisModule>(RedisModule);

});

我的课程存储库服务具有2个依赖项-Redis和Mongoose模型(课程)。 我想嘲笑他们两个。

如果我嘲笑提供程序,则可以使用以下语法:

providers: [
    {provide: CoursesRepository, useFactory: mockCoursesRepository},
     LessonsRepository
    ],

我可以创建一个模拟Redis服务,以在测试过程中代替实际的Redis服务吗?

如何?

谢谢, 雅伦

1 个答案:

答案 0 :(得分:4)

您可以像其他任何依赖项一样嘲笑RedisService。由于您确实对Redis客户端感兴趣,而不是对服务感兴趣,因此必须为该服务创建一个 intermediate 模拟。对于猫鼬,您需要使用getModelToken方法来获取正确的注入令牌,请参阅以下answer

const redisClientMockFactory = // ...
const redisServiceMock = {getClient: () => redisClientMockFactory()}

providers: [
  { provide: RedisService, useValue: redisServiceMock },
  { provide: getModelToken('Course'), useFactory: courseModelMockFactory },
  CoursesRepository
],

还请注意,您可能不应该在单元测试中导入模块(除非它是测试模块)。有关单元测试和e2e测试之间的区别,请参见此answer

如何创建模拟?

请参阅此answer