要使用sequelize作为ORM对mysql数据库执行单元测试,我需要在每个测试开始运行时刷新我的数据库。 实际上我写了这样一个解决方案:
beforeEach(() => {
table1.destroy({ where: {} })
table2.destroy({ where: {} })
table3.destroy({ where: {} })
})
但每次创建表时我都要添加另一条指令。 我将实现一条指令来执行整个模式的完整擦除
类似的东西:
beforeEach(() => db.clean())
答案 0 :(得分:2)
进行单元测试时,不应触摸数据库。
如果您正在测试与续集相关的业务逻辑,请创建一个模拟接口以进行续集并将其注入正在测试的单元中。然后,您可以对调用mock接口的方法进行断言或期望。如果没有测试环境的更多细节,那么提供更具体的方向是不可能的,但您可以调查sequelize-mocking包来促进这一点。
如果您正在测试sequelize实际上正在与您的数据库交谈,那么您所做的远不止是单元测试,我认为您需要一种带外初始化和管理方式环境,但我也指出,sequelize已经有一整套测试。
答案 1 :(得分:1)
sequelize.truncate()
这记录在:https://sequelize.org/master/class/lib/sequelize.js~Sequelize.html#instance-method-truncate 这会截断所有表,这似乎最接近您想要的:
<块引用>截断所有通过 sequelize 模型定义的表。这是通过在每个模型上调用 Model.truncate()
来完成的。
然后可以使用以下技术之一处理并行测试:https://sqa.stackexchange.com/questions/16854/designing-database-reliant-tests-for-parallel-execution/47244#47244 Will 的 mocking suggestion 也解决了并行问题,因此也可能值得研究。
最小可运行示例:
const assert = require('assert');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite',
});
const IntegerNames = sequelize.define(
'IntegerNames', {
value: { type: DataTypes.INTEGER, allowNull: false },
name: { type: DataTypes.STRING, },
});
const IntegerNames2 = sequelize.define(
'IntegerNames2', {
value: { type: DataTypes.INTEGER, allowNull: false },
name: { type: DataTypes.STRING, },
});
(async () => {
// Create and populate databases.
await IntegerNames.sync({force: true})
await IntegerNames.create({value: 2, name: 'two'});
await IntegerNames.create({value: 3, name: 'three'});
await IntegerNames2.sync({force: true})
await IntegerNames2.create({value: 4, name: 'four'});
await IntegerNames2.create({value: 5, name: 'five'});
// Check that they were populated.
assert((await IntegerNames.findAll()).length === 2);
assert((await IntegerNames2.findAll()).length === 2);
// Truncate them and check that they are empty.
await sequelize.truncate();
assert((await IntegerNames.findAll()).length === 0);
assert((await IntegerNames2.findAll()).length === 0);
// Cleanup.
await sequelize.close();
})();
当我们运行它时,Sequelize 会记录以下两个数据库行:
Executing (default): DELETE FROM `IntegerNames2s`
Executing (default): DELETE FROM `IntegerNames`
这似乎是它的 TRUNCATE 语句版本,根据:https://sqlite.org/lang_delete.html#the_truncate_optimization
在 6.5.1、Node v14.16.0 上测试。
另一种测试方法:SQLite 内存数据库
对于在 SQLite 上进行测试,这是一个很好的方法,可以确保每次都完全干净,您甚至不必担心截断或创建唯一的数据库名称
new Sequelize({
dialect: 'sqlite',
storage: ':memory:',
})