testing和使用书架/ Knex时“没有这样的表格:用户”

我试图运行一个简单的testing使用摩卡和我的Bookshelf / Knex模型,但是我得到错误“未处理的拒绝错误:SQLITE_ERROR:没有这样的表:用户”。 请注意,我试图在内存中使用SQLite。

这是我的Knexfile:

module.exports = { development: { client: 'sqlite3', connection: { filename: ':memory:' } }, test: { client: 'mysql', connection: { host: '172.18.0.2', user: 'root', password: '', database: 'staging_db', charset : 'utf8' }, pool: { min: 2, max: 10 }, migrations: { tableName: 'knex_migrations' } }, production: { client: 'mysql', connection: { host: process.env.DB_HOST || 'localhost', user: process.env.DB_USER || 'usr', password: process.env.DB_PWD || '', database: process.env.DB_NAME || 'db', charset : 'utf8' }, pool: { min: 2, max: 10 }, migrations: { tableName: 'knex_migrations' } } }; 

Database.js:

 var config = require('../knexfile.js'); var env = process.env.NODE_ENV || 'development'; var knex = require('knex')(config[env]); knex.migrate.latest([config]); let bookshelf = require('bookshelf')(knex); bookshelf.plugin('registry'); // Resolve circular dependencies with relations // Export bookshelf for use elsewhere module.exports = bookshelf; 

和我的用户模式:

 let bookshelf = require('../config/database'); require('./role'); var User = bookshelf.Model.extend({ tableName: 'users', role: function() { return this.hasOne(Role); } }); module.exports = bookshelf.model('user', User); 

而我的testing:

 var User = require('../../models/user'), chai = require('chai'), expect = chai.expect; describe('User model', function () { it('should return empty set before adding anything', () => { expect(User.collection().count()).to.equal(0); }); }); 

我错过了什么吗?

UPDATE

添加迁移文件:

 exports.up = function(knex, Promise) { return knex.schema.createTable('roles', function (table) { //this creates an id column as auto incremented primary key table.increments(); table.string('description', 45).notNullable(); }) .createTable('users', function (table) { table.increments(); table.string('name', 60); table.string('password', 45); table.integer('role_id').unsigned(); table.foreign('role_id').references('roles.id'); }); }; exports.down = function(knex, Promise) { return knex.schema.dropTable('users').dropTable('roles'); }; 

首先:你的testing是错误的: count()返回一个计数诺言,而不是计数本身。 所以改变你的testing:

 it('should return empty set before adding anything', function(done) { User .collection() .count() .then(count => { expect(count).to.equal(0); done() }) .catch(err => done(err)); }); 

第二:testing和迁移之间有竞争条件。

如果您在knexfile.js上启用Knexdebugging模式

 //... development: { client: 'sqlite3', connection: { filename: ':memory:' }, debug: true }, //... 

你会得到

 $ ./node_modules/mocha/bin/_mocha ./test/user.js Knex:warning - sqlite does not support inserting default values. Set the `useNullAsDefault` flag to hide this warning. (see docs http://knexjs.org/#Builder-insert). User model [ { sql: 'select * from sqlite_master where type = \'table\' and name = ?', output: [Function: output], bindings: [ 'knex_migrations' ] } ] [ { sql: 'create table if not exists "knex_migrations" ("id" integer not null primary key autoincrement, "name" varchar(255), "batch" integer, "migration_time" datetime)', bindings: [] } ] { method: 'select', options: {}, timeout: false, cancelOnTimeout: false, bindings: [], __knexQueryUid: '7186321c-92b5-416c-8a5f-304118e47a0d', sql: 'select count(*) as "count" from "users"' } [ { sql: 'select * from sqlite_master where type = \'table\' and name = ?', output: [Function: output], bindings: [ 'knex_migrations_lock' ] } ] 1) should return empty set before adding anything [ { sql: 'create table if not exists "knex_migrations_lock" ("is_locked" integer)', bindings: [] } ] { method: 'select', options: {}, timeout: false, cancelOnTimeout: false, bindings: [], __knexQueryUid: '7ebd63cc-1070-4422-b664-47e28b58de15', sql: 'select * from "knex_migrations_lock"' } 0 passing (62ms) 1 failing 1) User model should return empty set before adding anything: select count(*) as "count" from "users" - SQLITE_ERROR: no such table: users Error: SQLITE_ERROR: no such table: users 

请注意count()查询发生在迁移仍在检查迁移表是否存在时。

一个简单(而且过于丑陋)的解决方法是在testing中增加一些延迟:

 describe('User model', function () { this.timeout(20000); before(function (done) { setTimeout(() => done(), 200); // 200ms was enough on my env }) it('should return empty set before adding anything', function (done) { User.collection().count() .then(count => { expect(count).to.equal(0); done() }) .catch(err => done(err)); }); }); 

你会高兴地得到

 $ ./node_modules/mocha/bin/_mocha ./test/user.js Knex:warning - sqlite does not support inserting default values. Set the `useNullAsDefault` flag to hide this warning. (see docs http://knexjs.org/#Builder-insert). User model ✓ should return empty set before adding anything 1 passing (225ms) 

注意testing运行稍微超过200毫秒。

另一种可能的方法是将迁移添加到before()子句中。 这将使你能够使用他们的await