如何用Jest模拟Sequelize? [英] How to mock Sequelize with Jest?
问题描述
我正在尝试编写代码的单元测试,这些代码调用Sequelize创建数据库.
I am trying to write unit tests for code which makes calls to Sequelize to create a database.
我终生无法弄清楚如何模拟对Sequelize的调用,以便断言它们已正确创建了数据库表.
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.
我命中Sequelize的代码如下:
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();
};
理想情况下,我想断言每个数据库都正确地调用了define
,正确地调用了hasMany
并为每个数据库调用了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
因为它不是函数,所以无法监视authenticate属性;取而未定义.
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);
});
});
我不确定spyOn
是否是正确的调用方法,或者我是否可以/如何使用jest.mock
模拟并检查对Sequelize
的调用.
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
.
推荐答案
我将使用 jest.mock(模块名称,工厂,选项)以手动模拟sequelize
模块.
I am going to use jest.mock(moduleName, factory, options) to mock sequelize
module manually.
单元测试解决方案:
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);
});
});
单元测试结果:
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
这篇关于如何用Jest模拟Sequelize?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!