如何使用 jest 模拟 Knex
How to mock Knex using jest
我正在尝试使用 jest 模拟 knex 以实现以下实现
const knex = Knex({ client: "mysql"})
const query = knex("table_name")
.where({
title: "xxx-yyy",
lang: "eng"
})
.select()
.orderBy('date', 'desc')
.toSQL()
.toNative()
下面我试过了,但没有用,出现错误“TypeError: knex is not a function”
jest.mock("knex", () => {
return () => {
return {
knex: () => {
where: () => {
select: () => {
orderBy: () => {
toSQL: () => {
toNative: jest.fn()
}
}
}
}
}
}
}
})
非常感谢任何帮助。
jest.mock()
将模拟具有自动模拟版本的模块,factory
和 options
是可选的。
您可以使用 mockFn.mockReturnThis() 模拟方法链调用。
另外,如果你在模块作用域内初始化Knex
,你需要require
在设置mock之后模块。
例如
index.js
:
import Knex from 'knex';
const knex = Knex({ client: 'mysql' });
export function main() {
const query = knex('table_name')
.where({
title: 'xxx-yyy',
lang: 'eng',
})
.select()
.orderBy('date', 'desc')
.toSQL()
.toNative();
}
index.test.js
:
import Knex from 'knex';
jest.mock('knex');
describe('68717941', () => {
test('should pass', () => {
const querybuilder = {
where: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
orderBy: jest.fn().mockReturnThis(),
toSQL: jest.fn().mockReturnThis(),
toNative: jest.fn(),
};
const mKnex = jest.fn().mockReturnValue(querybuilder);
Knex.mockReturnValue(mKnex);
const { main } = require('./');
main();
expect(Knex).toBeCalledWith({ client: 'mysql' });
expect(mKnex).toBeCalledWith('table_name');
expect(querybuilder.where).toBeCalledWith({ title: 'xxx-yyy', lang: 'eng' });
expect(querybuilder.select).toBeCalledTimes(1);
expect(querybuilder.orderBy).toBeCalledWith('date', 'desc');
expect(querybuilder.toSQL).toBeCalledTimes(1);
expect(querybuilder.toNative).toBeCalledTimes(1);
});
});
测试结果:
PASS examples/68717941/index.test.js (8.844 s)
68717941
✓ should pass (7464 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.439 s
检查我写的一个小库 knex-mock-client,它允许你编写一个单元测试,使用 DB 而不是真正的 DB :]。
这种方法的好处是,您不需要了解所有 Knex's
内部信息(这可能会随着时间的推移而改变),并且它允许您控制“数据库”应该 return 的数据针对特定查询。
用法示例:
// my-cool-controller.ts
import { db } from '../common/db-setup';
export async function addUser(user: User): Promise<{ id }> {
const [insertId] = await db.insert(user).into('users');
return { id: insertId };
}
// my-cool-controller.spec.ts
import { expect } from '@jest/globals';
import knex, { Knex } from 'knex';
import { getTracker, MockClient } from 'knex-mock-client';
import faker from 'faker';
jest.mock('../common/db-setup', () => {
return {
db: knex({ client: MockClient })
};
});
describe('my-cool-controller tests', () => {
let tracker: Tracker;
beforeAll(() => {
tracker = getTracker();
});
afterEach(() => {
tracker.reset();
});
it('should add new user', async () => {
const insertId = faker.datatype.number();
tracker.on.insert('users').response([insertId]);
const newUser = { name: 'foo bar', email: 'test@test.com' };
const data = await addUser(newUser);
expect(data.id).toEqual(insertId);
const insertHistory = tracker.history.insert;
expect(insertHistory).toHaveLength(1);
expect(insertHistory[0].method).toEqual('insert');
expect(insertHistory[0].bindings).toEqual([newUser.name, newUser.email]);
});
});
我正在尝试使用 jest 模拟 knex 以实现以下实现
const knex = Knex({ client: "mysql"})
const query = knex("table_name")
.where({
title: "xxx-yyy",
lang: "eng"
})
.select()
.orderBy('date', 'desc')
.toSQL()
.toNative()
下面我试过了,但没有用,出现错误“TypeError: knex is not a function”
jest.mock("knex", () => {
return () => {
return {
knex: () => {
where: () => {
select: () => {
orderBy: () => {
toSQL: () => {
toNative: jest.fn()
}
}
}
}
}
}
}
})
非常感谢任何帮助。
jest.mock()
将模拟具有自动模拟版本的模块,factory
和 options
是可选的。
您可以使用 mockFn.mockReturnThis() 模拟方法链调用。
另外,如果你在模块作用域内初始化Knex
,你需要require
在设置mock之后模块。
例如
index.js
:
import Knex from 'knex';
const knex = Knex({ client: 'mysql' });
export function main() {
const query = knex('table_name')
.where({
title: 'xxx-yyy',
lang: 'eng',
})
.select()
.orderBy('date', 'desc')
.toSQL()
.toNative();
}
index.test.js
:
import Knex from 'knex';
jest.mock('knex');
describe('68717941', () => {
test('should pass', () => {
const querybuilder = {
where: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
orderBy: jest.fn().mockReturnThis(),
toSQL: jest.fn().mockReturnThis(),
toNative: jest.fn(),
};
const mKnex = jest.fn().mockReturnValue(querybuilder);
Knex.mockReturnValue(mKnex);
const { main } = require('./');
main();
expect(Knex).toBeCalledWith({ client: 'mysql' });
expect(mKnex).toBeCalledWith('table_name');
expect(querybuilder.where).toBeCalledWith({ title: 'xxx-yyy', lang: 'eng' });
expect(querybuilder.select).toBeCalledTimes(1);
expect(querybuilder.orderBy).toBeCalledWith('date', 'desc');
expect(querybuilder.toSQL).toBeCalledTimes(1);
expect(querybuilder.toNative).toBeCalledTimes(1);
});
});
测试结果:
PASS examples/68717941/index.test.js (8.844 s)
68717941
✓ should pass (7464 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.439 s
检查我写的一个小库 knex-mock-client,它允许你编写一个单元测试,使用 DB 而不是真正的 DB :]。
这种方法的好处是,您不需要了解所有 Knex's
内部信息(这可能会随着时间的推移而改变),并且它允许您控制“数据库”应该 return 的数据针对特定查询。
用法示例:
// my-cool-controller.ts
import { db } from '../common/db-setup';
export async function addUser(user: User): Promise<{ id }> {
const [insertId] = await db.insert(user).into('users');
return { id: insertId };
}
// my-cool-controller.spec.ts
import { expect } from '@jest/globals';
import knex, { Knex } from 'knex';
import { getTracker, MockClient } from 'knex-mock-client';
import faker from 'faker';
jest.mock('../common/db-setup', () => {
return {
db: knex({ client: MockClient })
};
});
describe('my-cool-controller tests', () => {
let tracker: Tracker;
beforeAll(() => {
tracker = getTracker();
});
afterEach(() => {
tracker.reset();
});
it('should add new user', async () => {
const insertId = faker.datatype.number();
tracker.on.insert('users').response([insertId]);
const newUser = { name: 'foo bar', email: 'test@test.com' };
const data = await addUser(newUser);
expect(data.id).toEqual(insertId);
const insertHistory = tracker.history.insert;
expect(insertHistory).toHaveLength(1);
expect(insertHistory[0].method).toEqual('insert');
expect(insertHistory[0].bindings).toEqual([newUser.name, newUser.email]);
});
});