Mocha 使用 Knex 测试 PostgreSQL 时出现 MigrationLocked 错误
Mocha testing PostgreSQL with Knex is giving me a MigrationLocked error
我有一个为 Node/PostgreSQL/Knex 工作的本地开发环境,因为我可以使用 API post 到我机器上的开发数据库。我现在正在尝试为此功能创建测试,但出现错误。
这是我的配置:
//knexfile.js
module.exports = {
development: {
client: 'pg',
connection: {
host: '127.0.0.1',
user: 'dbUser',
password: 'dbpword',
port: 5432,
database: 'example-name'
},
migrations: {
directory: __dirname + '/db/migrations'
},
seeds: {
directory: __dirname + '/db/seeds/development'
}
},
}
//db.js
const config = require('../knexfile.js');
const env = process.env.NODE_ENV || 'development';
const knex = require("knex")(config[env]);
module.exports = knex;
knex.migrate.latest([config]);
然后是我的测试:
import chai from 'chai';
import { expect } from 'chai';
import chaiHttp from 'chai-http';
import knex from '../../db/db';
import app from '../../server';
chai.use(chaiHttp);
describe('Tokens API', () => {
beforeEach((done) => {
knex.migrate.rollback()
.then(() => {
knex.migrate.latest()
.then(() => {
return knex.seed.run()
.then(() => {
done();
});
});
});
});
afterEach((done) => {
knex.migrate.rollback()
.then(() => {
done();
});
});
describe('POST /users', () => {
it('posts a list of users to the database with all mandatory fields', (done) => {
chai.request(app)
.post('/users')
.send({
"users": [
"steve",
"whoever",
"matt",
"another"]})
.end((err, res) => {
expect(err).to.be.null;
expect(res).to.have.status(200);
expect(res).to.be.json;
done();
});
});
});
});
当我 运行 这样做时,我两次收到以下错误 - 我认为对于 beforeEach 块中的 knex 调用:
Knex:warning - Can't take lock to run migrations: Migration table is already locked
Knex:warning - If you are sure migrations are not running you can release the lock manually by deleting all the rows from migrations lock table: knex_migrations_lock
Unhandled rejection MigrationLocked: Migration table is already locked
我已经尝试了很多事情 - 包括清除 knex_migrations_lock table。我可以在网上找到的唯一支持是 this 线程,它建议使用 DELETE FROM Migrations_lock where id <> 0;
清除锁 table,但是我的锁 table 只有一个 is_locked
列值为零。
知道发生了什么吗?
编辑: 我刚刚意识到,如果您编辑掉所有 knex 调用,测试实际上会通过。这可能是因为我有效地调用了 knex 两次——一次来自 db.js
,一次间接通过 server.js
?如果是这种情况,我该如何避免这样做 - 因为我肯定需要将 Node 的 knex 设置调用到 运行 它?
有完全相同的问题,最终是由于我 API 在由 supertest 库初始化时调用数据库。
比如我的测试文件:
var db = require('../db');
var api = require('../api');
var supertest = require('supertest')(api);
describe('Session routes', () => {
beforeEach((done) => {
db.migrate.rollback()
.then(() => {
db.migrate.latest()
.then(() => {
return db.seed.run()
.then(() => {
done();
});
});
});
});
afterEach((done) => {
db.migrate.rollback()
.then(() => {
done();
});
});
it('GET /session should error with no token', (done) => {
supertest
.get('/session')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(401, {
error: 'Unauthorized'
}, done);
});
});
在第 2 行,它需要我的 api - 当需要我的 api 时,以下代码会立即获取 运行 来初始化我的 api 的外部服务API:
var db = require('./other-postgres-library');
var servicesApi = require('./services/api')(db);
这将连接到一堆外部服务并将结果写入数据库。
因此,当测试 运行 时,我的应用程序抛出错误,因为它试图写入正在滚动的数据库 back/migrated/seeded 等
我更改了内部服务 API 以延迟初始化,所有问题都消失了。
在你的情况下,我会冒险猜测你何时测试 运行这一行
import app from '../../server';
您的 app/server 代码正在尝试 运行 对数据库进行一些查询。
对于遇到此问题的任何人,问题实际上来自 db.js
,特别是最后一行:
const config = require('../knexfile.js');
const env = process.env.NODE_ENV || 'development';
const knex = require("knex")(config[env]);
module.exports = knex;
knex.migrate.latest([config]);
当然这是异步的,测试在尝试 运行 自己的 knex 函数之前导入此文件,导致锁定。我通过在测试时添加一个子句来阻止这个 运行ning 来解决这个问题:
if(process.env.NODE_ENV != 'test') {
knex.migrate.latest([config])
}
然后您可以通过向每个规范文件添加 process.env.NODE_ENV='test'
或安装 npm env test 模块来创建测试环境。
我有一个为 Node/PostgreSQL/Knex 工作的本地开发环境,因为我可以使用 API post 到我机器上的开发数据库。我现在正在尝试为此功能创建测试,但出现错误。
这是我的配置:
//knexfile.js
module.exports = {
development: {
client: 'pg',
connection: {
host: '127.0.0.1',
user: 'dbUser',
password: 'dbpword',
port: 5432,
database: 'example-name'
},
migrations: {
directory: __dirname + '/db/migrations'
},
seeds: {
directory: __dirname + '/db/seeds/development'
}
},
}
//db.js
const config = require('../knexfile.js');
const env = process.env.NODE_ENV || 'development';
const knex = require("knex")(config[env]);
module.exports = knex;
knex.migrate.latest([config]);
然后是我的测试:
import chai from 'chai';
import { expect } from 'chai';
import chaiHttp from 'chai-http';
import knex from '../../db/db';
import app from '../../server';
chai.use(chaiHttp);
describe('Tokens API', () => {
beforeEach((done) => {
knex.migrate.rollback()
.then(() => {
knex.migrate.latest()
.then(() => {
return knex.seed.run()
.then(() => {
done();
});
});
});
});
afterEach((done) => {
knex.migrate.rollback()
.then(() => {
done();
});
});
describe('POST /users', () => {
it('posts a list of users to the database with all mandatory fields', (done) => {
chai.request(app)
.post('/users')
.send({
"users": [
"steve",
"whoever",
"matt",
"another"]})
.end((err, res) => {
expect(err).to.be.null;
expect(res).to.have.status(200);
expect(res).to.be.json;
done();
});
});
});
});
当我 运行 这样做时,我两次收到以下错误 - 我认为对于 beforeEach 块中的 knex 调用:
Knex:warning - Can't take lock to run migrations: Migration table is already locked
Knex:warning - If you are sure migrations are not running you can release the lock manually by deleting all the rows from migrations lock table: knex_migrations_lock
Unhandled rejection MigrationLocked: Migration table is already locked
我已经尝试了很多事情 - 包括清除 knex_migrations_lock table。我可以在网上找到的唯一支持是 this 线程,它建议使用 DELETE FROM Migrations_lock where id <> 0;
清除锁 table,但是我的锁 table 只有一个 is_locked
列值为零。
知道发生了什么吗?
编辑: 我刚刚意识到,如果您编辑掉所有 knex 调用,测试实际上会通过。这可能是因为我有效地调用了 knex 两次——一次来自 db.js
,一次间接通过 server.js
?如果是这种情况,我该如何避免这样做 - 因为我肯定需要将 Node 的 knex 设置调用到 运行 它?
有完全相同的问题,最终是由于我 API 在由 supertest 库初始化时调用数据库。
比如我的测试文件:
var db = require('../db');
var api = require('../api');
var supertest = require('supertest')(api);
describe('Session routes', () => {
beforeEach((done) => {
db.migrate.rollback()
.then(() => {
db.migrate.latest()
.then(() => {
return db.seed.run()
.then(() => {
done();
});
});
});
});
afterEach((done) => {
db.migrate.rollback()
.then(() => {
done();
});
});
it('GET /session should error with no token', (done) => {
supertest
.get('/session')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(401, {
error: 'Unauthorized'
}, done);
});
});
在第 2 行,它需要我的 api - 当需要我的 api 时,以下代码会立即获取 运行 来初始化我的 api 的外部服务API:
var db = require('./other-postgres-library');
var servicesApi = require('./services/api')(db);
这将连接到一堆外部服务并将结果写入数据库。
因此,当测试 运行 时,我的应用程序抛出错误,因为它试图写入正在滚动的数据库 back/migrated/seeded 等
我更改了内部服务 API 以延迟初始化,所有问题都消失了。
在你的情况下,我会冒险猜测你何时测试 运行这一行
import app from '../../server';
您的 app/server 代码正在尝试 运行 对数据库进行一些查询。
对于遇到此问题的任何人,问题实际上来自 db.js
,特别是最后一行:
const config = require('../knexfile.js');
const env = process.env.NODE_ENV || 'development';
const knex = require("knex")(config[env]);
module.exports = knex;
knex.migrate.latest([config]);
当然这是异步的,测试在尝试 运行 自己的 knex 函数之前导入此文件,导致锁定。我通过在测试时添加一个子句来阻止这个 运行ning 来解决这个问题:
if(process.env.NODE_ENV != 'test') {
knex.migrate.latest([config])
}
然后您可以通过向每个规范文件添加 process.env.NODE_ENV='test'
或安装 npm env test 模块来创建测试环境。