如何在 Service 构造函数中对 Controller 进行单元测试和模拟 @InjectModel
Posted
技术标签:
【中文标题】如何在 Service 构造函数中对 Controller 进行单元测试和模拟 @InjectModel【英文标题】:How to unit test Controller and mock @InjectModel in the Service constructor 【发布时间】:2019-03-23 12:01:28 【问题描述】:我在对我的控制器进行单元测试时遇到问题并收到错误消息“Nest 无法解析我的服务的依赖项”。
为了获得最大的覆盖率,我想对控制器和相应的服务进行单元测试,并想模拟像猫鼬连接这样的外部依赖项。同样,我已经尝试过以下链接中提到的建议,但没有找到任何运气:
https://github.com/nestjs/nest/issues/194#issuecomment-342219043
请在下面找到我的代码:
export const deviceProviders = [
provide: 'devices',
useFactory: (connection: Connection) => connection.model('devices', DeviceSchema),
inject: ['DbConnectionToken'],
,
];
export class DeviceService extends BaseService
constructor(@InjectModel('devices') private readonly _deviceModel: Model<Device>)
super();
async getDevices(group): Promise<any>
try
return await this._deviceModel.find( Group: group ).exec();
catch (error)
return Promise.reject(error);
@Controller()
export class DeviceController
constructor(private readonly deviceService: DeviceService)
@Get(':group')
async getDevices(@Res() response, @Param('group') group): Promise<any>
try
const result = await this.deviceService.getDevices(group);
return response.send(result);
catch (err)
return response.status(422).send(err);
@Module(
imports: [MongooseModule.forFeature([ name: 'devices', schema: DeviceSchema ])],
controllers: [DeviceController],
components: [DeviceService, ...deviceProviders],
)
export class DeviceModule
单元测试:
describe('DeviceController', () =>
let deviceController: DeviceController;
let deviceService: DeviceService;
const response =
send: (body?: any) => ,
status: (code: number) => response,
;
beforeEach(async () =>
const module = await Test.createTestingModule(
controllers: [DeviceController],
components: [DeviceService, ...deviceProviders],
).compile();
deviceService = module.get<DeviceService>(DeviceService);
deviceController = module.get<DeviceController>(DeviceController);
);
describe('getDevices()', () =>
it('should return an array of devices', async () =>
const result = [
Group: 'group_abc',
DeviceId: 'device_abc',
,
Group: 'group_xyz',
DeviceId: 'device_xyz',
];
jest.spyOn(deviceService, 'getDevices').mockImplementation(() => result);
expect(await deviceController.getDevices(response, null)).toBe(result);
);
);
);
当我在上面运行我的测试用例时,我遇到了两个错误:
Nest 无法解析 DeviceService (?) 的依赖关系。请确保索引 [0] 处的参数在当前上下文中可用。
无法窥探原始值;给定的未定义
【问题讨论】:
【参考方案1】:您没有在此处注入正确的令牌。您必须使用函数getModelToken
而不是纯字符串。
import getModelToken from '@nestjs/mongoose';
// ...
provide: getModelToken('devices'), useFactory: myFactory ,
【讨论】:
【参考方案2】:示例代码:
import Test from '@nestjs/testing';
import getModelToken from '@nestjs/mongoose';
describe('auth', () =>
let deviceController: DeviceController;
let deviceService: DeviceService;
const mockRepository =
find()
return ;
;
beforeAll(async () =>
const module = await Test.createTestingModule(
imports: [DeviceModule]
)
.overrideProvider(getModelToken('Auth'))
.useValue(mockRepository)
.compile();
deviceService = module.get<DeviceService>(DeviceService);
);
// ...
);
【讨论】:
以上是关于如何在 Service 构造函数中对 Controller 进行单元测试和模拟 @InjectModel的主要内容,如果未能解决你的问题,请参考以下文章
如何在Node.js中对使用promises和事件发射器的函数进行单元测试?
在 service.subscribe 中组件的构造函数中的 Angular 更新不起作用