使用 knex 和 sqlite3 的Node.js方法的测试永远不会停止



我想做什么

我正在尝试测试使用knexnode.js函数。

不仅仅是嘲笑knex,我认为在内存数据库中实际运行测试很有趣,这使得这个测试不是严格的单一的,但对我来说,这是测试repository类的唯一有用方法。

这也是这里投票最多的答案:https://stackoverflow.com/a/32749601/1187067

我在测试中使用了什么

  • 基于knex的简化图书存储库bookRepo.js
  • 测试bookRepo.test.js注入基于SQLite3knex连接。

问题

数据库初始化良好,测试成功,afterEach()函数被很好地调用,但该过程永远不会结束,这对于管道来说尤其成问题。

我发现停止该过程的唯一方法是在bookRepo.js和bookRepo.test.js中调用knex.destroy(),但不可能销毁knex,因为不可能多次使用它。

感谢您的帮助!

法典

书回购.js

const knex = require('connection'); // dependency not injected in constructor
const TABLE = 'books';
class BookRepo {
constructor() {
this.knex = knex;
}
static getTable() {
return TABLE;
}
async getTitleById(id) {
const book = await this.knex(TABLE)
.select('title')
.where('id', id)
.first();
return book.title;
}
}
module.exports = BookRepo;

bookRepo.test.js

const { assert } = require('chai');
const mock = require('mock-require');
const {
describe,
it,
before,
after,
beforeEach,
afterEach,
} = require('mocha');
const sqliteConf = {
client: 'sqlite3',
connection: {
filename: ':memory:',
},
useNullAsDefault: true,
};
const knex = require('knex')(sqliteConf);
const booksTable = BookRepo.getTable();
const BOOK_1 = {
id: 1,
title: 'Batman',
};
let bookRepo;
describe('getTitleById', () => {
before(() => {
// To use sqlite3 in the tested module, replace knexfile (required by connections)
mock('../knexfile', {
development: sqliteConf,
});
// as knex is not injected in constructor, we need to require BookRepo after having mocked knexfile.
const BookRepo = require('../bookRepo');
bookRepo = new BookRepo();
});
after(() => {
mock.stopAll();
knex.destroy(); // destroys only the connection of the test, not in bookRepo
});
/**
* We initialize the SQLite database before each test (create table and insert)
*/
beforeEach(async () => {
// drop table
await knex.schema.dropTableIfExists(booksTable);
// create table
await knex.schema.createTable(booksTable, (table) => {
table.integer('id');
table.string('title');
});
// Insertion
await knex.transaction((t) => knex(booksTable)
.transacting(t)
.insert(BOOK_1)
.then(t.commit)
.catch(t.rollback))
.catch((e) => {
console.error(e);
throw new Error('failed to insert test data');
});
});
/**
* We drop the SQLite table after each test
*/
afterEach(async () => {
await knex.schema.dropTableIfExists(booksTable); // table well dropped
});
it('returns the title of the given book', async () => {
const bookRepo = new BookRepo();
const expectedTitle = BOOK_1.title;
const retrievedTitle = await bookRepo.getTitleById(BOOK_1.id);
assert.equal(retrievedTitle, expectedTitle); // OK
});
});

包.json

…
dependencies": {
"knex": "^0.20.1",
},
"devDependencies": {
"chai": "latest",
"mocha": "^6.2.2",
"sqlite3": "latest",
}
}

既然你使用的是摩卡,似乎最好使用摩卡的after钩并从那里调用destroy。同样,您可以在before中实例化 Knex。我想不出您需要在非测试代码中调用destroy的原因。

最新更新