我想用模拟服务为我的http控制器编写单元测试。其主要思想是模拟服务并为其提供一些模拟实现。
下面是我完成此操作的设置(我将跳过一些imports语句,并在我们的上下文装饰器中无用,以减少代码行数):
create-user.http.controller.ts:
export class CreateUserHttpController {
constructor(
@Inject(createUserSymbol)
private readonly createUser: CreateUserService,
) {}
@Post(appRoutes.users.root)
async create(@Body() body: CreateUserRequest): Promise<IdResponse> {
const command = new CreateUserCommand({
email: body.email,
name: body.name,
password: body.password,
role: 'user',
});
const id = await this.createUser.createUser(command);
return new IdResponse(id.value);
}
}
create-user.http.controller.spec.ts:
import { Test } from '@nestjs/testing';
import { ID } from 'src/core/value-objects/id.value-object';
import { createUserSymbol } from '../../user.providers';
import { CreateUserHttpController } from './create-user.http.controller';
import { CreateUserService } from './create-user.service';
jest.mock('./create-user.service', () => {
return {
CreateUserService: jest.fn().mockImplementation(() => {
return {
createUser: () => {
console.log('ts');
},
};
}),
};
});
describe('CreateUserHttpController', () => {
let createUserHttpController: CreateUserHttpController;
let createUserService: CreateUserService;
beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
controllers: [CreateUserHttpController],
providers: [
{
provide: createUserSymbol,
useValue: CreateUserService,
},
],
}).compile();
createUserHttpController = await moduleRef.resolve(
CreateUserHttpController,
);
createUserService = await moduleRef.resolve(createUserSymbol);
});
describe('create', () => {
it('should call once createUser method in service', async () => {
const expectedResult = new ID('test');
jest
.spyOn(createUserService, 'createUser')
.mockResolvedValue(expectedResult);
const result = await createUserHttpController.create({
email: 'test@mail.ru',
name: 'test',
password: 'test',
});
expect(createUserService).toHaveBeenCalledTimes(1);
});
});
});
在这个设置中,我遇到了这样的问题:(不能监视属性,因为它不是函数;而是未定义的)

我尝试过console.log模拟服务实例,以检查是否存在“createUser”属性。看上去好像不在那里。

我已经很深入地检查了jest文档,尤其是这里- 用于模拟非默认类导出的jest doc。。我花了大约6个小时,尝试了所有可用的选择,但结果仍然是一样的。
我也查过这里的指南- 介质导轨。这个幸运的家伙似乎有相同的设置,没有任何问题。
因此,从我的角度来看,由于某种原因,jest.mock函数似乎没有使用createUser方法初始化模拟服务。
任何帮助都很感激!提前谢谢。
发布于 2021-07-11 17:55:48
我明白这是怎么回事了。在createUserSymbol的自定义提供程序中,您使用的是为CreateUserService创建的模拟,但是这个模拟是一个工厂,而不是一个直接值,所以您应该使用useFactory代替useValue,这样Nest就可以最终调用工厂函数。如果你移除jest.fn().mockImplementation(),只需看一下会有什么
{
CreateUserService: () => {
return {
createUser: () => {
console.log('ts');
}
}
}
}因此,要获得返回的对象,您需要首先调用函数,即CreateUserService(),或者,正如前面提到的,您可以使用useFactory,Nest将为您调用该方法。
另一个不同的选择是完全放弃jest.mock(),只需将一个自定义值传递给Nest以进行模拟,如
const moduleFixture = await Test.createTestingModule({
controllers: [CreateUserController],
providers: [
{
provide: createUserSymbol,
useValue: {
createUse: jest.fn().mockImplementation(() => console.log('ts'))
}
}
],
}).compile();这种方法也可以测试模块不可知论,因此,如果出于任何原因决定更改库,则可以更容易地交换
https://stackoverflow.com/questions/68330931
复制相似问题