在node.js中测试后清理数据库

时间:2014-03-05 12:01:15

标签: node.js postgresql npm database-cleaner knex.js

如何在每次 后清理数据库?

在rails中我使用https://github.com/bmabey/database_cleaner,但我没有找到类似于node.js

的东西

node.js(v0.10.26),PostgreSQL(9.3.3),mocha,restify和knex。

4 个答案:

答案 0 :(得分:3)

有一个好的套餐,请查看:https://github.com/emerleite/node-database-cleaner/

答案 1 :(得分:3)

我使用database-cleaner package清除数据库之前 {strong> it 指令和db-migrate包重置数据库< strong>在运行测试之前。

在设置下方。

将以下devDependencies添加到您的package.json

"devDependencies": {
  "chai": "^3.5.0",
  "database-cleaner": "^1.1.0",
  "mocha": "^3.0.2",
  "db-migrate": "^0.10.0-beta.15",
  "db-migrate-pg": "^0.1.10",
  ...
}

这是项目结构:

.
├── config
│   ├── cleaner-config.js
│   ├── db.js
│   └── ...
├── db
│   ├── database.json
│   └── migrations
│       ├── ...
│       └── sqls
│           └── ...
├── node_modules
├── scripts
│   └── test
├── ...
├── src
│   ├── db.js
│   ├── models
│   └── ...
└── test
    ├── init.js
    └── src
        └── ...

cleaner-config.js

module.exports = {
  postgresql: {
    skipTables: ['migrations']
  }
};

用于获取数据库配置的config/db.js

// Prepare default DB config
const defaultOptions = function(environment = 'development') {
  const host = 'db';
  const port = 5432;
  const user = process.env.POSTGRES_USER;
  const password = process.env.POSTGRES_PASSWORD;

  var conf = {
    host: host,
    port: port,
    user: user,
    password: password,
    database: process.env.POSTGRES_DB,
    max: 10, // max number of clients in the pool
    idleTimeoutMillis: 30000 // Keeps idle connections open for a 30 seconds
  };

  // Change the used database in test environment
  if (environment === 'test') {
    conf.database = require('../db/database.json').test.database;
  }

  return conf;
};

// Return database configuration for all environments
module.exports = {
  development: defaultOptions(),
  test: defaultOptions('test')
};

src/db.js文件负责建立数据库连接:

const PgPool = require('pg-pool');

// create a config to configure both pooling behavior and client options
const CONFIG = require('../config/db')[process.env.NODE_ENV || 'development'];

// Initializes connection pool
const pool = new PgPool(CONFIG);

module.exports = function(callback) {
  pool.on('error', function(error, client) {
    // if an error is encountered by a client while it sits idle in the pool
    // the pool itself will emit an error event with both the error and
    // the client which emitted the original error
    // this is a rare occurrence but can happen if there is a network partition
    // between your application and the database, the database restarts, etc.
    // and so you might want to handle it and at least log it out
    console.error('idle client error', error.message, error.stack);
  });

  // to run a query we can acquire a client from the pool,
  // run a query on the client, and then return the client to the pool
  pool.connect(function(error, client, done) {
    if (error)
      return console.error('error fetching client from pool', error);

    callback(client, done);
  });
};

test数据库在database.json(也用于)中进行了硬编码:

{
  "test": {
    "driver": "pg",
    "user": {
      "ENV": "POSTGRES_USER"
    },
    "password": {
      "ENV": "POSTGRES_PASSWORD"
    },
    "host": "db",
    "database": "<prefix>_test"
  },
  "development": {
    "driver": "pg",
    "user": {
      "ENV": "POSTGRES_USER"
    },
    "password": {
      "ENV": "POSTGRES_PASSWORD"
    },
    "host": "db",
    "database": {
      "ENV": "POSTGRES_DB"
    }
  },
  "sql-file": true
}

我在test/init.js文件的末尾加载了所有测试:

DB = {
  client: null,
  closeConnection: null
}

beforeEach(function(done) {
  require('../src/db')(function(client, dbDone) {
    DB.client = client;
    DB.closeConnection = dbDone;

    var DatabaseCleaner = require('database-cleaner');
    var databaseCleaner = new DatabaseCleaner('postgresql');

    databaseCleaner.clean(client, done);
  });
});

// TODO: close connection only once - at the end of testing
afterEach(function(done) {
  DB.client = null;
  DB.closeConnection();
  done();
});

require('./src/<some library>.test');
...

最后但并非最不重要的是用于运行测试的scripts/test脚本:

#!/bin/bash

script_directory="$( cd "$( dirname "$0" )" && pwd )"
project_directory=$script_directory/..

# Stop execution and exit on any error
set -e

cd $project_directory

db_name='<prefix>_test'

# Drop the DB
# Use the development environment because of this issue: https://github.com/db-migrate/node-db-migrate/issues/393
./node_modules/.bin/db-migrate --env development --migrations-dir db/migrations --config db/database.json db:drop $db_name
# Create the DB
# Use the development environment because of this issue: https://github.com/db-migrate/node-db-migrate/issues/393
./node_modules/.bin/db-migrate --env development --migrations-dir db/migrations --config db/database.json db:create $db_name

./node_modules/.bin/db-migrate --env test --migrations-dir db/migrations --config db/database.json up

NODE_ENV=test ./node_modules/.bin/mocha test/init.js

答案 2 :(得分:2)

您可以将测试包装到事务中:

beforeEach(() => {
    return connection.query('START TRANSACTION');
});
afterEach(() => {
    return connection.query('ROLLBACK');
});

与清理相比,以这种方式运行测试要快得多,或者在每次测试后更糟糕地删除/重新创建模式。

如果将其与池化连接(new Pool())一起使用,则需要将连接数限制为1:new Pool({min:1, max:1}) - 事务必须跨越单个连接。

Postgresql支持嵌套事务,因此在测试期间不会与其他事务发生冲突。

答案 3 :(得分:1)

我发现在测试之间清理数据库的简单方法是

DROP SCHEMA public CASCADE;
CREATE SCHEMA public AUTHORIZATION my_test_user;

一旦公共模式属于测试用户,他就可以在需要时删除并重新创建模式。请注意删除数据库的公共模式中的所有内容。