node.js 如何对连接到 mongo 的方法进行单元测试,而不实际连接到 mongo?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25585569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 17:50:32  来源:igfitidea点击:

How to unit test a method which connects to mongo, without actually connecting to mongo?

node.jsmongodbmochachaichai-as-promised

提问by Catfish

I'm trying to write a test to test a method that connects to mongo, but I don't actually want to have to have mongo running and actually make a connection to it to have my tests pass successfully.

我正在尝试编写一个测试来测试连接到 mongo 的方法,但我实际上不想让 mongo 运行并实际连接它以使我的测试成功通过。

Here's my current test which is successful when my mongo daemon is running.

这是我当前的测试,当我的 mongo 守护进程运行时它是成功的。

describe('with a valid mongo string parameter', function() {
    it('should return a rejected promise', function(done) {
        var con = mongoFactory.getConnection('mongodb://localhost:27017');
        expect(con).to.be.fulfilled;
        done();
    });
});

mongoFactory.getConnection code:

mongoFactory.getConnection 代码:

getConnection: function getConnection(connectionString) {

      // do stuff here

        // Initialize connection once
        MongoClient.connect(connectionString, function(err, database) {
          if (err) {
            def.reject(err);
          }

          def.resolve(database);
        });

      return def.promise;
    }

回答by zamnuts

There are a couple of SO answers related to unit testing code that uses MongoDB as a data store:

有几个与使用 MongoDB 作为数据存储的单元测试代码相关的 SO 答案:

I'll make an attempt at consolidating these solutions.

我将尝试整合这些解决方案。

Preamble

前言

First and foremost, you shouldwant MongoDB to be running while performing your tests. MongoDB's query language is complex, so running legitimate queries against a stable MongoDB instance is required to ensure your queries are running as planned and that your application is responding properly to the results. With this in mind, however, you should neverrun your tests against a production system, but instead a peripheral system to your integration environment. This can be on the same machine as your CI software, or simply relatively close to it (in terms of process, not necessarily network or geographically speaking).

首先,您应该希望 MongoDB 在执行测试时运行。MongoDB 的查询语言很复杂,因此需要针对稳定的 MongoDB 实例运行合法查询,以确保您的查询按计划运行并且您的应用程序正确响应结果。但是,考虑到这一点,您永远不应针对生产系统运行测试,而应针对集成环境的外围系统运行测试。这可以与您的 CI 软件在同一台机器上,或者只是相对接近它(就进程而言,不一定是网络或地理上的)。

This ENV could be low-footprint and completely run in memory (resource 1) (resource 2), but would not necessarily require the same performance characteristics as your production ENV. (If you want to performance test, this should be handled in a separate environment from your CI anyway.)

此 ENV 可能占用空间很小,并且完全在内存(资源 1)(资源 2)中运行,但不一定需要与生产 ENV 相同的性能特征。(如果你想进行性能测试,这应该在与你的 CI 不同的环境中处理。)

Setup

设置

  • Install a mongodservice specifically for CI.If repl sets and/or sharding are of concern (e.g. write concern, no use of $isolated, etc.), it is possible to mimic a clustered environment by running multiple mongodinstances (1 config, 2x2 data for shard+repl) and a mongosinstance on the same machine with either some init.d scripts/tweaks or something like docker.
  • Use environment-specific configurationswithin your application (either embedded via .json files, or in some place like /etc, /home/user/.your-app or similar). Your application can load these based on a node environment variable like NODE_ENV=int. Within these configurations your db connection strings will differ. If you're notusing env-specific configs, start doing this as a means to abstract the application runtime settings (i.e. "local", "dev", "int", "pre", "prod", etc.). I can provide a sample upon request.
  • Include test-oriented fixtures with your application/testing suite.As mentioned in one of the linked questions, MongoDB's Node.js driver supports some helper libraries: mongodb-fixturesand node-database-cleaner. Fixtures provide a working and consistent data set for testing: think of them as a bootstrap.
  • 安装mongod专门用于 CI的服务。如果 repl 集和/或分片受到关注(例如写关注、不使用$isolated等),则可以通过运行多个mongod实例(1 个配置,分片 + 复制的 2x2 数据)和一个mongos实例来模拟集群环境带有一些 init.d 脚本/调整或类似 docker 的东西的同一台机器。
  • 在您的应用程序中使用特定环境的配置(通过 .json 文件嵌入,或在诸如 /etc、/home/user/.your-app 或类似的地方)。您的应用程序可以根据节点环境变量(如NODE_ENV=int. 在这些配置中,您的数据库连接字符串会有所不同。如果您使用特定于 env 的配置,请开始执行此操作以抽象应用程序运行时设置(即“local”、“dev”、“int”、“pre”、“prod”等)。我可以根据要求提供样品。
  • 在您的应用程序/测试套件中包含面向测试的装置。如链接问题之一所述,MongoDB 的 Node.js 驱动程序支持一些帮助程序库:mongodb-fixturesnode-database-cleaner. Fixtures 为测试提供了一个有效且一致的数据集:将它们视为引导程序。

Builds/Tests

构建/测试

  1. Clean the associated database using something like node-database-cleaner.
  2. Populate your fixtures into the now empty database with the help of mongodb-fixtures.
  3. Perform your build and test.
  4. Repeat.
  1. 使用类似node-database-cleaner.
  2. 借助mongodb-fixtures.
  3. 执行您的构建和测试。
  4. 重复。

On the other hand...

另一方面...

If you still decide that notrunning MongoDB is the correct approach (and you wouldn't be the only one), then abstracting your data store calls from the driver with an ORM is your best bet (for the entire application, not just testing). For example, something like modelclaims to be database agnostic, although I've never used it. Utilizing this approach, you would still require fixturesand env configurations, however you would not be required to install MongoDB. The caveat here is that you're at the mercy of the ORM you choose.

如果您仍然认为运行 MongoDB 是正确的方法(并且您不会是唯一的方法),那么使用 ORM 从驱动程序中抽象出您的数据存储调用是您最好的选择(对于整个应用程序,而不仅仅是测试) . 例如,像model声称与数据库无关的东西,尽管我从未使用过它。使用这种方法,您仍然需要夹具和环境配置,但是您不需要安装 MongoDB。这里需要注意的是,您受所选择的 ORM 的支配。

回答by Alex Lapa

You could try tingodb.

你可以试试tingodb

TingoDB is an embedded JavaScript in-process filesystem or in-memory database upwards compatible with MongoDB at the API level.

TingoDB 是一个嵌入式 JavaScript 进程内文件系统或内存数据库,在 API 级别与 MongoDB 向上兼容。