Reputation: 424
I am trying to write unit tests for code which makes calls to Sequelize to create a database.
I cannot for the life of me figure out how to mock out calls to Sequelize such that I can assert they have created the database tables correctly.
My code which hits Sequelize is as follows:
import { Sequelize, DataTypes } from "sequelize";
export setup_db = async (db_path: string) => {
//Get read/write connection to database
const sequelizeContext = new Sequelize({
dialect: "sqlite",
storage: db_path,
});
//Check if connection is secure, throw error if not
try {
await sequelizeContext.authenticate();
} catch (err) {
throw err;
}
//Define first table
const Table1 = sequelizeContext.define(
"table1",
{
fieldName_1: {
type: DataTypes.STRING
}
},
{ tableName: "table1" }
);
//Define second table
const Table2 = sequelizeContext.define(
"table2",
{
fieldName_1: {
type: DataTypes.STRING
},
{tablename: "table2"}
});
//Define relationship between tables... each Gamertag hasMany wzMatches
Table1.hasMany(Table2);
await Table1.sync();
await Table2.sync();
};
Ideally, I would like to assert that define
was called properly, hasMany
was called properly, and sync
was called for each database.
My test code currently is as follows, although it throws an error about
Cannot spy the authenticate property because it is not a function; undefined given instead.
import { setup_db } from "../../core/dataManager";
const Sequelize = require("sequelize").Sequelize;
describe("DataManager.setup_db", () => {
it("should call sequelize to correctly set up databases", async () => {
//Arrange
const authenticateSpy = jest.spyOn(Sequelize, "authenticate");
//Act
await setup_db("path/to/db.db");
//Assert
expect(authenticateSpy).toHaveBeenCalledTimes(1);
});
});
I'm not sure if spyOn
is the right method to call, or whether I can/how I can use jest.mock
to mock out and inspect calls to Sequelize
.
Upvotes: 11
Views: 30758
Reputation: 102367
I am going to use jest.mock(moduleName, factory, options) to mock sequelize
module manually.
Unit test solution:
index.ts
:
import { Sequelize, DataTypes } from 'sequelize';
export const setup_db = async (db_path: string) => {
const sequelizeContext = new Sequelize({
dialect: 'sqlite',
storage: db_path,
});
try {
await sequelizeContext.authenticate();
} catch (err) {
throw err;
}
const Table1 = sequelizeContext.define(
'table1',
{
fieldName_1: {
type: DataTypes.STRING,
},
},
{ tableName: 'table1' },
);
const Table2 = sequelizeContext.define(
'table2',
{
fieldName_1: {
type: DataTypes.STRING,
},
},
{ tableName: 'table2' },
);
(Table1 as any).hasMany(Table2);
await Table1.sync();
await Table2.sync();
};
index.test.ts
:
import { setup_db } from './';
import { Sequelize, DataTypes } from 'sequelize';
import { mocked } from 'ts-jest/utils';
jest.mock('sequelize', () => {
const mSequelize = {
authenticate: jest.fn(),
define: jest.fn(),
};
const actualSequelize = jest.requireActual('sequelize');
return { Sequelize: jest.fn(() => mSequelize), DataTypes: actualSequelize.DataTypes };
});
const mSequelizeContext = new Sequelize();
describe('64648688', () => {
afterAll(() => {
jest.resetAllMocks();
});
it('should setup db correctly', async () => {
const mTable1 = { hasMany: jest.fn(), sync: jest.fn() };
const mTable2 = { sync: jest.fn() };
mocked(mSequelizeContext.define).mockImplementation((modelName): any => {
switch (modelName) {
case 'table1':
return mTable1;
case 'table2':
return mTable2;
}
});
await setup_db(':memory:');
expect(Sequelize).toBeCalledWith({ dialect: 'sqlite', storage: ':memory:' });
expect(mSequelizeContext.authenticate).toBeCalled();
expect(mSequelizeContext.define).toBeCalledWith(
'table1',
{
fieldName_1: {
type: DataTypes.STRING,
},
},
{ tableName: 'table1' },
);
expect(mSequelizeContext.define).toBeCalledWith(
'table2',
{
fieldName_1: {
type: DataTypes.STRING,
},
},
{ tableName: 'table2' },
);
expect(mTable1.hasMany).toBeCalledWith(mTable2);
expect(mTable1.sync).toBeCalledTimes(1);
expect(mTable2.sync).toBeCalledTimes(1);
});
});
unit test result:
PASS src/stackoverflow/64648688/index.test.ts (16.442s)
64648688
✓ should setup db correctly (11ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 91.67 | 100 | 100 | 90.91 | |
index.ts | 91.67 | 100 | 100 | 90.91 | 12 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 20.184s
Upvotes: 14