【问题标题】:Timeout when attempting to connect to mongo from jest unit tests尝试从笑话单元测试连接到 mongo 时超时
【发布时间】:2016-07-25 06:09:06
【问题描述】:

我想用 jest 和 mongoose 编写一些单元测试来验证与 mongo 的数据交互。

我不想在这里模拟 mongoose,因为我特别想验证创建/修改/处理 mongo 文档的方式。

package.json 配置为不模拟节点模块:

{
  "jest": {
    "unmockedModulePathPatterns": [
      "node_modules"
    ]
  }
}

在我的实际测试中,我设置了一个beforeAll()钩子来负责连接mongo:

const mongoose = require('mongoose');

describe('MyTest', () => {

  beforeAll((done) => {
    mongoose.connect('mongodb://127.0.0.1:27017/test');

    let db = mongoose.connection;

    db.on('error', (err) => {
      done.fail(err);
    });

    db.once('open', () => {
      done();
    });
  });

  it('has some property', () => {
    // should pass but actually never gets run
    expect(1).toBe(1);
  });
});

这是输出:

/usr/local/bin/node node_modules/jest-cli/bin/jest.js --verbose
Using Jest CLI v0.10.0, jasmine2
 FAIL  src/lib/controllers/my-controller/__tests__/my-test.js (5.403s)
MyTest
  ✕ it has some property

MyTest › it has some property
  - Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
        at Timer.listOnTimeout (timers.js:92:15)
1 test failed, 0 tests passed (1 total in 1 test suite, run time 5.903s)

Process finished with exit code 1

测试每次都会超时,因为在 beforeAll() 钩子中从未调用过 done() - 没有抛出错误,也没有任何内容打印到控制台。我可以在beforeAll() 挂钩中放置断点来验证代码正在运行。似乎 mongoose 在尝试打开与 Mongo 的连接时挂起,然后开玩笑的测试超时。

当我在 jest 环境之外运行类似代码时,它会按预期连接(几乎立即启动)。怀疑这可能会导致问题,我尝试完全禁用 jest 的 automock 功能,但行为保持不变。

我想我错过了一些非常明显的事情......有什么想法会发生什么吗?

  • jest-cli v. 0.10.0
  • 猫鼬 v. 4.4.11

更新:

  • 尝试将 ES6 箭头函数语法替换为纯 function(done) {}。没有区别。
  • 尝试通过传递done 参数使测试异步,并在测试完成时调用它。没有区别。
  • 在声明errorconnected 事件处理程序后尝试调用mongoose.connect()
  • 尝试注释掉所有与 mongoose 相关的代码,以检查 beforeAll() 挂钩是否正常工作 - 确实如此。

【问题讨论】:

  • 有点远射,但您是否尝试过使用 function(done) 而不是 ES6 箭头语法?有一些细微的差别。
  • 你可以试试下面吗? it('has some property', (done) => { // should pass but actually never gets run expect(1).toBe(1); done(); });
  • 谢谢 - 尝试了这两个建议都无济于事,将添加到我的描述中。
  • 尝试将mongoose.connect移到db.once('open')下方,如果没有帮助,请将db.once('open')替换为db.on('connected')
  • @AlexanderMac - 试过了也没什么区别。

标签: node.js mongodb unit-testing mongoose jestjs


【解决方案1】:

Jest-jasmine 不同于 Jasmine
您使用的语法实际上属于 Jasmine 2.0+,而不是 Jest-jasmine。因此,如果您想继续使用 jest,则必须查看 jest 文档以找到答案。
更重要的是,“beforeAll”不是标准的开玩笑注入变量,请参阅jest api

我用 Jasmine 2.3.4 运行了你的代码,它运行得很好。我开玩笑地尝试了 Promise/pit 来完成这项工作,但失败了。

首先,install jasmine

npm install -g jasmine
mkdir jasmine-test  
cd jasmine-test
jasmine init
jasmine examples
touch spec/mongodbspec.js

这是我的目录结构:

fenqideMacBook-Pro:jasmine-test fenqi$ ls -R
.:
spec/

./spec:
mongodbspec.js  support/

./spec/support:
jasmine.json

然后,编辑 spec/mongodbspec.js,我只需在您的代码中添加一行“'use strict';”。

'use strict';

const mongoose = require('mongoose');

describe('MyTest', () => {

  beforeAll((done) => {
    mongoose.connect('mongodb://127.0.0.1:27017/test');

    let db = mongoose.connection;

    db.on('error', (err) => {
      done.fail(err);
    });

    db.once('open', () => {
      done();
    });
  });

  it('has some property', () => {
    // should pass but actually never gets run
    expect(1).toBe(1);
  });
});

最后,运行“茉莉花”:

fenqideMacBook-Pro:jasmine-test fenqi$ jasmine
Started
.


1 spec, 0 failures
Finished in 0.023 seconds

【讨论】:

  • 感谢您的调查 - 知道我的代码没有明显损坏确实很有帮助!原谅我,但你在这里回答了一个不同的问题:)。我知道 Jest 使用了不同风格的 Jasmine,并且这些钩子在技术上没有记录(但它们确实有效)。我想利用 Jest 的内置 automock 和覆盖等。
  • 很抱歉没有解决您的问题。也许您可以破解 Jest 以支持该语法,但正如我所尝试的那样,它可能会很复杂。
猜你喜欢
  • 1970-01-01
  • 2021-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多