在 mocha、chai 中使用 await/async

Usk*_*ske 5 mocha.js node.js express 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);
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

我在“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.
Run Code Online (Sandbox Code Playgroud)

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

Val*_*Shi 7

这一切都很简单。

为了避免该错误,您不得在 Mocha 中同时使用done和。async/await使用async/await或删除两者done作为函数参数和done()调用。或者使用done. 然后将两者都删除async/await。请参阅下面针对每种情况的示例测试。

使用try/catchwith 的async/await方式与通常将其与同步代码一起使用一样。

以下是最基本的 Mocha 测试,使用这两种async/await方法done测试相同的基本 HTTP 服务器端点。

这是async/await方法。

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

这是done方法。

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

请参阅完整的测试文件片段

对于工作示例,另外旋转基本 Express 服务器作为src/app.js.

有关请求测试的详细信息,请参阅Chai HTTP插件文档。

就是这个。


小智 5

我遇到了同样的问题,还没有找到一种方法来获得任何涉及mongoose与 Mocha/Chai 合作的承诺。

可以帮助您的是做我所做的并将您的猫鼬代码放入脚本中,以便您可以使用node <scriptfile>.js. 您可以使用它来确认它本身是否正常工作。在我的测试中,猫鼬操作在不到一秒钟的时间内完成。您还可以从另一个(非测试相关的)调用该文件以确认它正确执行并返回一个承诺。您可以从我的示例中看到如何确保正确关闭 db。部分示例:

  ...
  db.close();

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

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

在浪费了太多时间试图找出这种疯狂的行为之后,我所做的工作是在路线中执行我的猫鼬需求。我将需要使用它的每个请求包装end在额外的块中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
    }
  });
Run Code Online (Sandbox Code Playgroud)

请注意,使用try/catch上面的语法将导致通常无法显示通过的测试,并且结果将在 catch 块中捕获。如果您想避免这种情况,只需删除try/catch.


use*_*611 0

你是如何实施的./models/userawait仅在User.remove()返回承诺时有效,而不是在需要回调时有效。我会将调试信息添加到您的User.remove()函数中,以查看它在哪里被卡住。