NestJS如何在单元测试中创建新的猫鼬模型?

时间:2019-05-23 19:32:45

标签: testing mongoose model jestjs nestjs

我试图对我的NestJs Controller类进行单元测试。我已经使用ts-mockito模拟了我的服务,但是现在我很难创建想要返回的猫鼬对象,并且希望被控制器返回。我如何设法创建新的模型对象进行测试?

这是我的服务

@Injectable()
export class ProjectService {
    constructor(
        @InjectModel('Project') private readonly projectModel: Model<Project>,
        private tagService: TagService,
    ) {} ...

这是我的模特

    name: {type: String, required: true},
    description: String,
    created: {type: Date, default: Date.now},
});
export const ProjectSchema = schema;

export interface Project extends Document {
    readonly name: string,
    readonly description: string,
    readonly created: Date,
}

这是我的模块:

@Module({
    imports: [
        MongooseModule.forFeature([{ name: 'Project', schema: ProjectSchema }]),
    ],
    controllers: [
        ProjectController
    ],
    providers: [
        ProjectService,
    ],
})
export class ProjectModule {}

这是我的测试

describe('ProjectController', async () => {
    let projectController: ProjectController;
    let projectServiceMock: ProjectService = mock(ProjectService);
    let projectModel: Model<Project>;

    beforeAll(async () => {
        projectModel = mock(Model);

        const module: TestingModule = await Test.createTestingModule({
            controllers: [ProjectController],
            providers: [
                {
                    provide: ProjectService,
                    useValue: instance(projectServiceMock)
                },
                {
                    provide: 'Project',
                    useValue: instance(projectModel)
                }
            ]
        }).compile();

        projectController = module.get<ProjectController>(ProjectController);
    });

现在,我正在尝试创建一个新的Project对象,并从我的服务中返回它,并希望它从控制器中获得:

it('should return Project with id from projectService', async () => {
            const project = new projectModel({name: 'ProjectName', description: 'ProjectDescription'});

            let result = Promise.resolve(project);
            when(projectServiceMock.getById('projectId')).thenReturn(result);

            await expect(projectController.getById('projectId')).toEqual(result);
        });

但是我得到这个错误:

Nest cannot find given element (it does not exist in current context)

      25 | 
      26 |         projectController = module.get<ProjectController>(ProjectController);
    > 27 |         projectModel = module.get<Model<Project>>('Project');
         |                               ^
      28 |     });
      29 | 
      30 |     describe('getAll', async () => {

正如我认为我可以从错误消息中读取的那样,将模型“测试”到测试中肯定有问题,但是我真的不知道如何在不启动连接的情况下获得模型。 我能做什么?您有适合您的示例代码吗?

1 个答案:

答案 0 :(得分:0)

为了测试模型,可以使用mockingoose库。除了模拟整个模型之外,还将模拟相关的方法。我在测试中使用的模式如下:

package.json

{devDependencies: {
  "mockingoose": "^2.13.2"
  }
}

测试文件:

controller.spec.ts

import * as mongoose from 'mongoose';
import mockingoose from 'mockingoose';
import { getModelToken } from '@nestjs/mongoose';

const ProjectModel = mongoose.model('ProjectSchema', ProjectSchema);

// Duplicate the following line to mock all the methods that are called in your tests
// In this case, the 'save' method is mocked, and returns 'mockedReturnValueOfSaveMethod'
mockingoose(ProjectModel).toReturn(mockedReturnValueOfSaveMethod, 'save');

beforeAll(async () => {
  const module = await Test.createTestingModule({
    providers: [
      {
        provide: getModelToken('Project'), 
        useValue: ProjectModel // The mocked model will be correctly injected...
      }
    ]
  });
});

其他注意事项...

尽管我在解决方案中引入了新的依赖关系,但减少应用程序开发和部署中使用的依赖关系的数量仍被认为是一种很好的做法。根据测试文件的结构,我想您正在使用笑话。我不知道您的整体测试结构,但是请考虑使用jest.mock而不是ts-mockito方法;关于在打字稿中的用法,有广泛的documentation