【问题标题】:Cleaning database after tests in node.js在 node.js 中测试后清理数据库
【发布时间】:2014-04-07 11:24:23
【问题描述】:

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

在 Rails 中我使用 https://github.com/bmabey/database_cleaner,但我没有为 node.js 找到类似的东西

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

【问题讨论】:

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


    【解决方案1】:

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

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

    与清理相比,以这种方式运行测试会快得多,甚至比在每次测试后删除/重新创建架构更糟糕。

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

    但是,如果正在测试的代码也使用事务,这将不起作用。可以使用保存点进行嵌套事务,但可能会变得更复杂。

    【讨论】:

      【解决方案2】:

      我使用database-cleaner package 清理数据库之前 每个it 指令和db-migrate 包重置数据库之前 运行测试。

      设置下方。

      将以下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
      

      【讨论】:

        【解决方案3】:

        有一个不错的包,看看:https://github.com/emerleite/node-database-cleaner/

        【讨论】:

          【解决方案4】:

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

          DROP SCHEMA public CASCADE;
          CREATE SCHEMA public AUTHORIZATION my_test_user;
          

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多