Testing 使用TypeORM和Nestjs进行测试的过程,以及使用mock进行jest的过程?

Testing 使用TypeORM和Nestjs进行测试的过程,以及使用mock进行jest的过程?,testing,tdd,nestjs,typeorm,Testing,Tdd,Nestjs,Typeorm,这个问题可能会推广到服务中的存根存储库,以及如何在这个问题的上下文中正确测试和提供覆盖范围。 我正在学习更多关于测试的知识,但是我一直在学习如何正确地执行涉及数据库的测试 我有一个用户实体,它定义了列和一些初始验证逻辑 从“类验证器”导入{IsAlphanumeric,IsEmail,MinLength}; 从“typeorm”导入{Column,Entity,PrimaryGeneratedColumn}; @实体() 导出类用户{ @PrimaryGeneratedColumn() 公众id

这个问题可能会推广到服务中的存根存储库,以及如何在这个问题的上下文中正确测试和提供覆盖范围。

我正在学习更多关于测试的知识,但是我一直在学习如何正确地执行涉及数据库的测试

我有一个用户实体,它定义了列和一些初始验证逻辑

从“类验证器”导入{IsAlphanumeric,IsEmail,MinLength};
从“typeorm”导入{Column,Entity,PrimaryGeneratedColumn};
@实体()
导出类用户{
@PrimaryGeneratedColumn()
公众id!:号码;
@第()列
公共名称!:字符串;
@IsEmail()
@第()列
公共电子邮件!:字符串;
@最小长度(8)
@第()列
公共密码!:字符串;
}
我有一个UserService,它为实体注入存储库

从'@nestjs/common'导入{Injectable};
从'@nestjs/typeorm'导入{InjectRepository};
从“类验证器”导入{validateorject};
从“typeorm”导入{Repository};
从“./dto/create user.dto”导入{CreateUserDTO};
从“./User.entity”导入{User};
@可注射()
导出类用户服务{
建造师(
@InjectRepository(用户)专用只读用户存储库:存储库
) {}
公共异步创建(dto:CreateUserDTO){
const user=this.userRepository.create(dto);
等待ValidateOrject(用户);
等待这个.userRepository.save(user);
}
公共异步findAll():承诺{
return wait this.userRepository.find();
}
公共异步findByEmail(电子邮件:字符串):承诺{
返回等待this.userRepository.findOne({
其中:{
电子邮件,
},
});
}
}
这是我的初步测试,所以你可以按照我的思路

从'@nestjs/testing'导入{Test,TestingModule};
从'@nestjs/typeorm'导入{getRepositoryToken};
从“./User.entity”导入{User};
从“/user.service”导入{UserService};
const createMock=jest.fn((dto:any)=>{
返回dto;
});
const saveMock=jest.fn((dto:any)=>{
返回dto;
});
const MockRepository=jest.fn().mockImplementation(()=>{
返回{
create:createMock,
save:saveMock,
};
});
const mockRepository=新建mockRepository();
描述('UserService',()=>{
let服务:UserService;
之前(异步()=>{
常量模块:TestingModule=等待测试。createTestingModule({
供应商:[
用户服务,
{
提供:getRepositoryToken(用户),
useValue:mockRepository,
},
],
}).compile();
service=module.get(UserService);
});
它('应该定义',()=>{
expect(service.toBeDefined();
});
它('不应创建无效用户',异步()=>{
// ??
});
});

因此,虽然我可以进行测试运行和一切,但我不确定我实际上应该测试什么。很明显,我可以在create上测试它是否有效,对于findAll之类的其他东西,我觉得我只是在模拟数据库?为了正确地测试这一点,是否需要将其连接到数据库,以便检查是否返回了正确的数据


nest文档说“我们通常希望避免任何数据库连接”,但这样做不是违背了目的,因为我们没有真正测试功能吗?因为虽然我可以模拟save返回一个值,但我不会测试唯一列、可空数据、要设置的递增值等可能出现的任何错误。。。对吗?

许多人认为针对db进行测试是一种不好的做法。但正是出于您提到的原因,我省去了管理mock和stub的麻烦,我几乎总是在专用的测试数据库上运行测试


在我的jest初创公司中,我清除了所有的表,然后有助手帮助我根据需要创建具有关系的实体,以确保我的测试保持原子性。

@AyKarsi所建议的总比没有好,但这仍然是一种不好的做法

单元测试应该模拟数据库和第三方API调用

集成测试应该测试用真实数据库模拟的内容,并且只测试该部分

端到端测试用于检查整个应用程序是否连接良好


有关更多详细信息,请阅读:

好的,谢谢。我非常感谢您的反馈。我最终做了一些非常相似的事情。我决定对测试数据库使用sqljs,并设置TypeORM,以便在每次测试后删除数据库,并在每次测试开始时进行同步。它仍然非常快,就像你说的那样,大大简化了事情。谢谢一般来说,对数据库进行测试并没有什么坏处,只要它不是单元测试的一部分。实际上,在不访问数据库的情况下进行e2e测试是不可能的。因此,所有这些都取决于用例,唯一重要的部分是不要将所有测试混在一起。@AyKarsi我如何才能将真实的数据库库导入到我的测试模块中?我认为可以使用一次性数据库进行测试,例如SQLite
:memory:
,demo:@kenberkeley您的开发数据库应该与您的生产数据库匹配“我不确定我实际上应该测试什么”,确切地说,因为您的服务基本上没有什么可测试的。您唯一可以测试的是,您的服务是否正确调用了您希望它调用的存储库方法,并且使用了正确的参数,为此,您将使用“spyOn”或“TohavenCalledWith”“.TypeORM已经是一个经过测试的库,所以您不想测试TypeORM。针对数据库的测试是功能测试,而不是单元测试,在这种情况下,I w