sequelize.truncate({ cascade: true, restartIdentity: true })
This is documented at: https://sequelize.org/api/v6/class/src/sequelize.js~sequelize#instance-method-truncate this truncates all tables, which seems the closest to what you want:
Truncate all tables defined through the sequelize models. This is done by calling Model.truncate()
on each model.
and for the option
argument:
The options passed to Model.destroy
in addition to truncate
Parallel testing can then be handled with one of the techniques mentioned at: https://sqa.stackexchange.com/questions/16854/designing-database-reliant-tests-for-parallel-execution/47244#47244 Will's mocking suggestion also solves the parallel issue, so might be worth looking into as well.
The {truncate: cascade}
is required when foreign keys are involved, otherwise PostgreSQL 13.4 complains with:
cannot truncate a table referenced in a foreign key constraint
{truncate: cascade}
makes it run TRUNCATE "Mytable" CASCADE
instead of just TRUNCATE "MyTable"
, related:
The {restartIdentity: true}
can help make tests more reproducible by also resetting the primary key counter: How to reset autoIncrement primary key with sequelize? But note that it is broken on SQLite: https://github.com/sequelize/sequelize/issues/13286
Minimal runnable example:
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({ cascade: true, restartIdentity: true });
assert((await IntegerNames.findAll()).length === 0);
assert((await IntegerNames2.findAll()).length === 0);
// Cleanup.
await sequelize.close();
})();
When we run this, Sequelize logs the following two DB lines among others:
Executing (default): DELETE FROM `IntegerNames2s`
Executing (default): DELETE FROM `IntegerNames`
which seems to be its version of the TRUNCATE statement according to: https://sqlite.org/lang_delete.html#the_truncate_optimization
Tested on 6.5.1, Node v14.16.0.
Another testing approach: SQLite in-memory database
For testing on SQLite, this is a good approach that ensures that everything is completely clean each time, you don't even have to worry about truncating or creating unique database names
new Sequelize({
dialect: 'sqlite',
storage: ':memory:',
})