We use database to persist data. While running tests, we might insert or delete rows from the database. So it is a common practise to use a separate database for the purpose of testing. By doing this, we can easily create or destroy tables with peace of mind.
If we check the config.json file generated by sequelize-cli, it already has a configuration assigned to test. We will modify npm scripts to use this configuration for running tests.
First, we add a npm script in package.json to create the database for test purposes.
"scripts": {
"db:create:test": "NODE_ENV=test npx sequelize-cli db:create",
"test": "jest --detectOpenHandles",
"prepare": "husky install"
},Then we will add a script pretest which will run before running test script. Here we will delete the existing database from previous run as we need clean slate before each test run.
"scripts": {
"db:create:test": "NODE_ENV=test npx sequelize-cli db:create",
"pretest": "NODE_ENV=test npx sequelize-cli db:drop && NODE_ENV=test npx sequelize-cli db:create",
"test": "jest --detectOpenHandles",
"prepare": "husky install"
},And finally modify the test script to use the test database configuration.
"scripts": {
"db:create:test": "NODE_ENV=test npx sequelize-cli db:create",
"pretest": "NODE_ENV=test npx sequelize-cli db:drop && NODE_ENV=test npx sequelize-cli db:create",
"test": "NODE_ENV=test jest --detectOpenHandles",
"prepare": "husky install"
},Now, we can execute the scripts to create test database.
npm run db:create:testYou should see an output like the following:
> wd201@1.0.0 db:create:test
> NODE_ENV=test npx sequelize-cli db:create
Sequelize CLI [Node: 16.17.0, CLI: 6.4.1, ORM: 6.21.4]
Loaded configuration file "config/config.json".
Using environment "test".
Database todo_db_test created.
Now, we need to modify our tests to use the newly generated models. Edit __tests__/todo.js with following content. We will create the tables before running each tests.
// __tests__/todo.js
/* eslint-disable no-undef */
const db = require("../models");
describe("Todolist Test Suite", () => {
beforeAll(async () => {
await db.sequelize.sync({ force: true });
});
test("Should add new todo", async () => {
const todoItemsCount = await db.Todo.count();
await db.Todo.addTask({
title: "Test todo",
completed: false,
dueDate: new Date(),
});
const newTodoItemsCount = await db.Todo.count();
expect(newTodoItemsCount).toBe(todoItemsCount + 1);
});
});And your models/todo.js should look like:
// models/todo.js
'use strict';
const {
Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
class Todo extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static async addTask(params) {
return await Todo.create(params);
}
static associate(models) {
// define association here
}
displayableString() {
let checkbox = this.completed ? "[x]" : "[ ]";
return `${this.id}. ${checkbox} ${this.title} ${this.dueDate}`;
}
}
Todo.init({
title: DataTypes.STRING,
dueDate: DataTypes.DATEONLY,
completed: DataTypes.BOOLEAN
}, {
sequelize,
modelName: 'Todo',
});
return Todo;
};Next we can run the tests and it would use the credentials for test database.
npm testYou should see the tests getting executed and producing an output like the following:
PASS __tests__/todo.js
Todolist Test Suite
✓ Should add new todo (40 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.974 s, estimated 2 s
Ran all test suites.
In this lesson, we have learned how to configure and use a separate database for testing purposes.