我一直在成功使用Knex连接到后端数据库。但我希望能够对我的代码进行单元测试。有没有办法模拟数据库连接?
我尝试过使用proxyquire,但似乎无法让它发挥作用。
问题似乎与Knex的初始化方式有关。
var knex = require('knex')({
client: 'mysql',
connection: {}
});
我设置knex在我的单元测试中被嘲笑。
myService = proxyquire('../app/myService', {
'knex': knexProxy
});
我的服务包括knex。
var knex = require('knex').knex,
当我的服务运行查询时,它会失败。
var sql = knex("table_name");
sql.insert(rowToInsert, "auto_increment_id");
sql.then(function (insertId) {
resolve();
}, function (err) {
reject(err);
});
出于某种原因,我似乎无法在尝试连接之前捕获请求。
我也试图创建一个custom Knex Client,但这还没有成功。
答案 0 :(得分:1)
我一直在使用in-memory Sqlite3 databases进行自动化测试并取得了巨大成功。这不是真正的单元测试,但它的运行速度比MySQL或PostgreSQL快得多。我已发布有关此解决方案的更多详细信息on a different question。
答案 1 :(得分:1)
使用jest:
在您的应用根目录中创建文件/__mocks__/knex.js
:
module.exports = () => ({
select: jest.fn().mockReturnThis(),
from: jest.fn().mockReturnThis(),
where: jest.fn().mockReturnThis(),
first: jest.fn().mockReturnThis(),
then: jest.fn(function (done) {
done(null)
})
})
将所需的返回值传递给done
答案 2 :(得分:0)
我用玩笑来模拟knex,但是我必须定义一个包含我使用的方法的对象。 不是最优雅的解决方案,但是可以正常工作
let knexMock = () => {
const fn = () => {
return {
returning: function() {
return {
insert: jest.fn().mockImplementation(() => [123123])
}
},
insert: jest.fn()
}
}
fn.raw = jest.fn()
return fn
}
knex.mockImplementation(knexMock)
答案 3 :(得分:0)
我正在使用jest,您可以执行以下操作:
jest.mock('knex', () => {
const fn = () => {
return {
select: jest.fn().mockReturnThis(),
from: jest.fn().mockReturnThis(),
where: jest.fn().mockReturnThis(),
first: jest.fn().mockReturnThis(),
insert: jest.fn().mockReturnThis(),
raw: jest.fn().mockReturnThis(),
then: jest.fn(function (done) {
done(null)
})
}
}
return fn
})
答案 4 :(得分:0)
我编写了一个名为 knex-mock-client
的小库,它正是这样做的,它允许您使用模拟客户端设置数据库“连接”,该模拟客户端将跟踪您的呼叫并帮助您做出响应。
例如:
// 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 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]);
});
});