【问题标题】:UnhandledPromiseRejectionWarning. Warnings when running using npm run test未处理的承诺拒绝警告。使用 npm run test 运行时的警告
【发布时间】:2019-01-09 17:05:46
【问题描述】:

我是 MongoDB 的新手,我正在使用 mongoose 库来帮助我在 MongoDB 中存储数据。尽管我所有的 (mocha) 测试都通过了,但我仍然不断收到此错误:

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'name' of null
  at C:\MY STUFF\CODING\Projects\mongodb tutorial\mongodb-playlist\test\finding_test.js:33:21
  UnhandledPromiseRejectionWarning: Unhandled promise rejection. 
  This error originated either by throwing inside of an async function without a catch block, 
  or by rejecting a promise which was not handled with .catch()
  DeprecationWarning: Unhandled promise rejections are deprecated. 
  In the future, promise rejections that are not handled will terminate 
  the Node.js process with a non-zero exit code.

这是我的代码:

const assert = require('assert');
const MarioChar = require('../models/mariochar');


describe('Finding records', function(){
  // this.timeout(15000);
  var char;

  beforeEach(function(done){
    char = new MarioChar({
      name: 'Mario'
    });

    // now test it
    char.save().then(function(){
      // done(); 
    });
    done();
  });

  it('Finds one record from the database', function(done){
    // this.timeout(15000);
    MarioChar.findOne({name: 'Mario'}).then(function(result){
      assert(result.name === 'Mario');
      // done();
    });
    done();
  });

  it('Finds one record by ID from the database', function(done){

    MarioChar.findOne({_id: char._id}).then(function(result){
      assert(result._id.toString() === char._id.toString());
      // done();
    });
    done();
  });
});

为了消除这些错误/警告,我尝试了所有 cmets。

当我使用mocha --trace-warnings finding_test.js 运行时,我没有收到任何警告,但是如果我使用此命令npm run test 运行,我会收到这些警告。

发生了什么事?

【问题讨论】:

    标签: javascript node.js mongodb mongoose mocha.js


    【解决方案1】:

    你的错误是Cannot read property 'name' of null

    这意味着您正在尝试访问一个变量上名为 name 的属性,该变量应该指向一个对象,但实际上是 null

    您在代码中访问name 的唯一位置是:

    MarioChar.findOne({name: 'Mario'}).then(function(result){
      assert(result.name === 'Mario'); // <---- here
    });
    

    这意味着,在此代码运行时,您的数据库中没有带有name: 'Mario' 的文档。

    发生这种情况的原因是因为在您的 beforeEach 挂钩中您没有等待创建文档。

    您在创建之前调用done

    beforeEach(function(done){
      char = new MarioChar({
        name: 'Mario'
      });
    
      char.save().then(function(){
        // this part is called when the document is created
      });
      done(); // this executes before document is created
    });
    

    您应该在保存后调用它(也可以在出错时调用):

    beforeEach(function(done){
      char = new MarioChar({
        name: 'Mario'
      });
    
      char.save()
       .then(done)   // we are done when successful
       .catch(done); // and when erroring
    });
    

    您还应该能够使用异步函数以获得更好的可读性:

    beforeEach(async function() {
      char = await new MarioChar({
        name: 'Mario'
      }).save();
    });
    

    注意:您还有一些其他地方没有正确调用 done,例如在您的测试中(it 调用)。您还必须在这些回调中调用 done 或返回承诺。

    例如,这个:

    it('Finds one record from the database', function(done){
      MarioChar.findOne({name: 'Mario'}).then(function(result){
        assert(result.name === 'Mario');
      });
      done();
    });
    

    应该是:

    it('Finds one record from the database', function(done){
      MarioChar.findOne({name: 'Mario'}).then(function(result){
        assert(result.name === 'Mario');
        done(); // call done here
      })
      .catch(done); // and here
    });
    

    或者(返回一个承诺):

    it('Finds one record from the database', function(){
      return MarioChar.findOne({name: 'Mario'}).then(function(result){
        assert(result.name === 'Mario');
      });
    });
    

    或者(使用异步函数):

    it('Finds one record from the database', async function(){
      const result = await MarioChar.findOne({name: 'Mario'});
       assert(result.name === 'Mario');
    });
    

    【讨论】:

    • 应该是——不应该。 Mocha 天生支持​​ Promise,在样板代码中使用 done 结果,容易出现人为错误,我一直看到这个。这将导致测试超时和未处理的拒绝,当断言失败时永远不会调用done。完成此操作的正确方法是MarioChar.findOne(...).then(...).then(done, done)
    • 非常感谢大家的帮助。我能够修复这个finding_test.js。但是,我还有其他代码updating_test.js。它类似于上面的代码,只是对于it 块我得到这个错误UnhandledPromiseRejectionWarning: AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value: assert(result.name === 'Luigi') for MarioChar.findOneAndUpdate({name: 'Mario'}, {name: 'Luigi'}).then(function(){ MarioChar.findOne({_id:char._id}).then(function(result){ assert(result.name === 'Luigi'); done(); }); }); Help plz!
    • @estus 你是对的。我主要是寻求快乐的路径解决方案,但我进行了相应的编辑以处理错误。感谢您的评论。
    猜你喜欢
    • 2020-01-01
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多