node.js - 如何开玩笑模拟nestjs导入?
问题描述
我想为我的 nestjs 'Course' 存储库服务(依赖于 Mongoose 模型和 Redis 的服务)编写一个单元测试。
课程.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 服务使用吗?
如何 ?
谢谢,亚龙
解决方案
请注意,接受的答案模拟了提供者,如果它也由提供者提供,它将满足您的测试类的依赖关系TestingModule
。但是,它不是import
像所要求的那样嘲笑 s,这可能会有所不同。例如,如果您需要import
一些也依赖于模拟值的模块,这将不起作用:
// DOES NOT WORK
const module = await Test.createTestingModule({
imports: [
ModuleThatNeedsConfig,
],
providers: [
{ provide: ConfigService, useValue: mockConfig },
ExampleService, // relies on something from ModuleThatNeedsConfig
]
}).compile();
要模拟import
,您可以使用DynamicModule
导出模拟值的 a :
const module = await Test.createTestingModule({
imports: [
{
module: class FakeModule {},
providers: [{ provide: ConfigService, useValue: mockConfig }],
exports: [ConfigService],
},
ModuleThatNeedsConfig,
],
providers: [
ClassUnderTest,
]
}).compile();
由于这有点冗长,因此像这样的实用函数可能会有所帮助:
export const createMockModule = (providers: Provider[]): DynamicModule => {
const exports = providers.map((provider) => (provider as any).provide || provider);
return {
module: class MockModule {},
providers,
exports,
global: true,
};
};
然后可以像这样使用:
const module = await Test.createTestingModule({
imports: [
createMockModule([{ provide: ConfigService, useValue: mockConfig }]),
ModuleThatNeedsConfig,
],
providers: [
ClassUnderTest,
]
}).compile();
这通常有一个额外的好处,就是让您import
使用被测类的模块,而不是让测试provide
直接绕过模块和值。
const module = await Test.createTestingModule({
imports: [
createMockModule([{ provide: ConfigService, useValue: mockConfig }]),
ModuleThatNeedsConfig,
ModuleUnderTest,
],
}).compile();
const service = module.get(ClassUnderTest);
推荐阅读
- php - PHP curl从json文件发送PUT请求
- python - 从 pybullet 理解视图和投影矩阵
- swift - SwiftUI:仅在某些视图上在 iPad 上消失的弹出框
- ios - UIWindow 功能在 Xcode11.3 中不起作用吗?
- azure - 在 Azure 表存储服务中查询 PartitionKey 和 RowKey 语法
- java - Azure HTTPTrigger 发布请求上传文件
- java - IntelliJ 执行失败
- c# - Selenium WebDriver C#:即使元素被禁用,Element.Enabled 也会返回 True
- python - numpy 数组元数据更改
- sql - 根据最接近的日期从连接表日期返回单数行/值