在Mocha,Chai中使用Await / Async

时间:2018-08-03 14:55:48

标签: node.js express mocha chai

我对节点表达很陌生。 并且一直在尝试使用mocha,chai和chai-http编写测试代码。 这是源代码的一部分。

const mongoose = require('mongoose'),
  User = require('../../models/user');

const mongoUrl = 'mongodb://xxxxxxxxxxx';

describe('/test', function() {
  before('connect', function() {
    return mongoose.createConnection(mongoUrl);
  });

  beforeEach(async function(done) {
    try {
      await User.remove({}); // <-- This doesn't work
      chai.request('http://localhost:3000')
        .post('/api/test')
        .send(something)
        .end((err, res) => {
          if (err) return done(err);
          done();
        });
    } catch (error) {
      done(error);
    }
  });
});

然后我用“ npm test”(nyc mocha --timeout 10000 test / ** / *。js)得到以下错误。

Error: Timeout of 10000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

我从日志确认数据库连接正常。 似乎我在等待User.remove({})时收到超时错误。 我也尝试过其他方法,例如User.save() 但是,我遇到了同样的错误。 我需要对数据库模型和连接做一些特别的事情吗?

3 个答案:

答案 0 :(得分:2)

I had the same problem,但尚未找到一种方法来获得涉及mongoose与Mocha / Chai合作的任何承诺。

可能会帮助您执行我所做的事情,并将您的猫鼬代码放入脚本中,以便您可以使用node <scriptfile>.js运行它。您可以使用它来确认它本身是否正常工作。在我的测试中,猫鼬手术不到一秒钟就完成了。您还可以从另一个文件(与测试无关的文件)中调用该文件,以确认文件是否正确执行并返回承诺。您可以从我的example中了解如何确保正确关闭数据库。部分示例:

  ...
  db.close();

  return new Promise((resolve) => {
    db.on('disconnected', () => {
      console.log('***************************************Mongoose CONNECTION TERMINATED');
      resolve('user ready');
    });
  });
  ...

您还可以通过查看以下问题herehere找到一些线索。

在浪费大量时间试图弄清这种疯狂行为之后,我所做的工作是在一条路线上执行我的猫鼬需求。我将每个需要使用的请求包装在额外的end的{​​{1}}块中或使用异步处理。示例:

chai.request...

请注意,使用上述describe('something', () => { it('should do something and change it back', async () => { try { // change user password let re1 = await chai.request(app) .post('/users/edit') .set('authorization', `Bearer ${token}`) .send({ username: 'user@domain.com', password: 'password6', }); expect(re1.statusCode).to.equal(200); // change password back since before hook not working let re2 = await chai.request(app) .post('/users/edit') .set('authorization', `Bearer ${token}`) .send({ username: 'user@domain.com', password: 'password6', passwordNew: 'password', passwordConfirm: 'password', }); expect(re2.statusCode).to.equal(200); } catch (error) { // error stuff here } }); 语法将导致通常无法通过测试的测试,结果将被捕获在catch块中。如果要避免这种情况,只需删除try/catch

答案 1 :(得分:2)

这一切都非常简单。

为避免错误,您不能同时在Mocha中同时使用doneasync/await。使用async/await并删除done作为函数参数和done()调用。或使用done。然后删除两个async/await。两者请参见下面的示例测试。

try/catchasync/await一起使用,就像通常将其与同步代码一起使用一样。

以下是使用async/awaitdone方法测试同一基本HTTP服务器端点的最基本的Mocha测试。

这是async/await方法。

it('with async/await', async function() {
    const res = await chai.request(server)
        .get('/')
        .send();
    assert.equal(res.status, 200);
});

这是done方法。

it('with done & callbacks', (done) => {
    chai.request(server)
        .get('/')
        .end((err, res) => {
            assert.equal(res.status, 200);
            done();
        });
});

请参见full test file snippet

对于工作示例,请另外旋转basic Express server作为src/app.js中的测试对象。<​​/ p>

有关可以使用请求测试执行的操作的更多信息,请参见Chai HTTP插件文档。

就这样。

答案 2 :(得分:0)

您是如何实现./models/user的? await仅在User.remove()返回promise时才有效,而不是期望回调的情况下才有效。我会将调试信息添加到您的User.remove()函数中,以查看其卡在哪里。