Een UnhandledPromiseRejectionWarning krijgen bij het testen met mokka/chai

Dus ik test een onderdeel dat afhankelijk is van een gebeurteniszender. Hiervoor heb ik een oplossing bedacht met behulp van Promises with Mocha+Chai:

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
    done();
  }).catch((error) => {
    assert.isNotOk(error,'Promise error');
    done();
  });
});

Op de console krijg ik een ‘UnhandledPromiseRejectionWarning’, ook al wordt de weigerfunctie aangeroepen omdat deze onmiddellijk het bericht ‘AssertionError: Promise error’ toont

(node:25754) UnhandledPromiseRejectionWarning: Onverwerkte belofte
afwijzing (afwijzings-ID: 2): AssertionError: Beloftefout: verwacht
{ Object (bericht, showDiff, …) } is vals

  1. moet overgaan met de juiste gebeurtenis

En dan, na 2 seconden krijg ik

Fout: time-out van 2000 ms overschreden. Zorg ervoor dat de done() callback is
wordt gebeld in deze test.

Wat nog vreemder is sinds de catch-callback werd uitgevoerd (ik denk dat om de een of andere reden de assert-fout de rest van de uitvoering verhinderde)

Het grappige is dat als ik commentaar geef op de assert.isNotOk(error...), de test goed verloopt zonder enige waarschuwing in de console. Het ‘faalt’ nog steeds in die zin dat het de vangst uitvoert.
Maar toch kan ik deze fouten niet met belofte begrijpen. Kan iemand mij informeren?


Antwoord 1, autoriteit 100%

Het probleem wordt hierdoor veroorzaakt:

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

Als de bewering mislukt, wordt er een fout gegenereerd. Deze fout zorgt ervoor dat done()nooit wordt aangeroepen, omdat de code ervoor een fout heeft gemaakt. Dat is de oorzaak van de time-out.

De “Onverwerkte belofte afwijzing”wordt ook veroorzaakt door de mislukte bewering, want als er een fout wordt gegenereerd in een catch()-handler, en er is Als een volgende catch()-handlerwordt gebruikt, wordt de fout ingeslikt (zoals uitgelegd in dit artikel). De waarschuwing UnhandledPromiseRejectionWarningwaarschuwt u voor dit feit.

Als je op beloftes gebaseerde code in Mocha wilt testen, moet je er in het algemeen op vertrouwen dat Mocha zelf al beloften aankan. Je moet done()niet gebruiken, maar in plaats daarvan een belofte van je test teruggeven. Mocha zal dan zelf eventuele fouten opvangen.

Zoals dit:

it('should transition with the correct event', () => {
  ...
  return new Promise((resolve, reject) => {
    ...
  }).then((state) => {
    assert(state.action === 'DONE', 'should change state');
  })
  .catch((error) => {
    assert.isNotOk(error,'Promise error');
  });
});

Antwoord 2, autoriteit 6%

Ik kreeg deze foutmelding bij het stoten met sinon.

De oplossing is om het npm-pakket sinon-as-promisedte gebruiken bij het oplossen of afwijzen van beloften met stubs.

In plaats van …

sinon.stub(Database, 'connect').returns(Promise.reject( Error('oops') ))

Gebruik …

require('sinon-as-promised');
sinon.stub(Database, 'connect').rejects(Error('oops'));

Er is ook een oplossingsmethode (let op de s aan het einde).

Zie http://clarkdave.net /2016/09/node-v6-6-and-asynchronous-handled-promise-rejections


Antwoord 3, autoriteit 6%

De beweringbibliotheken in Mocha werken door een fout te genereren als de bewering niet correct was. Het genereren van een fout resulteert in een afgewezen belofte, zelfs wanneer deze wordt gegenereerd in de uitvoerderfunctie die wordt geleverd door de catch-methode.

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

In de bovenstaande code evalueert de error-object naar true, dus de assertion-bibliotheek genereert een fout… die nooit wordt opgevangen. Als gevolg van de fout wordt de methode donenooit aangeroepen. Mocha’s donecallback accepteert deze fouten, dus je kunt alle belofteketens in Mocha eenvoudig beëindigen met .then(done,done). Dit zorgt ervoor dat de done-methode altijd wordt aangeroepen en dat de fout op dezelfde manier wordt gerapporteerd als wanneer Mocha de fout van de bewering opvangt in synchrone code.

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then(((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
  })).then(done,done);
});

Ik waardeer dit artikelvoor het idee om . then(done,done) bij het testen van beloften in Mocha.


Antwoord 4, autoriteit 5%

Voor degenen die op zoek zijn naar de fout/waarschuwing UnhandledPromiseRejectionWarningbuiten een testomgeving, het kan waarschijnlijk zijn dat niemand in de code zorgt voor de eventuele fout in een belofte:

Deze code geeft bijvoorbeeld de waarschuwing weer die in deze vraag wordt vermeld:

new Promise((resolve, reject) => {
  return reject('Error reason!');
});

(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!

en het toevoegen van de .catch()of het afhandelen van de fout zou de waarschuwing/fout moeten oplossen

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).catch(() => { /* do whatever you want here */ });

Of gebruik de tweede parameter in de functie then

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).then(null, () => { /* do whatever you want here */ });

Antwoord 5

Ik heb met dit probleem te maken gehad:

(node:1131004) UnhandledPromiseRejectionWarning: Onverwerkte afwijzing van belofte (re
jection id: 1): TypeError: res.json is geen functie
(node:1131004) Afschrijvingswaarschuwing: niet-verwerkte afwijzingen van beloften worden afgeschaft.
In de toekomst zullen afwijzingen van beloftes die niet worden afgehandeld, de Node.j . beëindigen
s-proces met een exit-code die niet nul is.

Het was mijn fout, ik verving resobject in then(function(res), dus veranderde resin resultaat en nu is het werkt.

Fout

module.exports.update = function(req, res){
        return Services.User.update(req.body)
                .then(function(res){//issue was here, res overwrite
                    return res.json(res);
                }, function(error){
                    return res.json({error:error.message});
                }).catch(function () {
                   console.log("Promise Rejected");
              });

Correctie

module.exports.update = function(req, res){
        return Services.User.update(req.body)
                .then(function(result){//res replaced with result
                    return res.json(result);
                }, function(error){
                    return res.json({error:error.message});
                }).catch(function () {
                   console.log("Promise Rejected");
              });

Servicecode:

function update(data){
   var id = new require('mongodb').ObjectID(data._id);
        userData = {
                    name:data.name,
                    email:data.email,
                    phone: data.phone
                };
 return collection.findAndModify(
          {_id:id}, // query
          [['_id','asc']],  // sort order
          {$set: userData}, // replacement
          { "new": true }
          ).then(function(doc) {
                if(!doc)
                    throw new Error('Record not updated.');
                return doc.value;   
          });
    }
module.exports = {
        update:update
}

Antwoord 6

Hier is mijn ervaring met E7 async/await:

In het geval dat je een async helperFunction()hebt aangeroepen vanuit je test… (een verklaring met het ES7 asynctrefwoord, bedoel ik)

>zorg ervoor dat je dat aanroept als await helperFunction(whateverParams)(nou ja, natuurlijk, als je het eenmaal weet…)

En om dat te laten werken (om te voorkomen dat ‘wachten een gereserveerd woord is’), moet uw testfunctie een buitenste asynchrone markering hebben:

it('my test', async () => { ...

Antwoord 7

Ik had een soortgelijke ervaring met Chai-Webdriver voor Selenium.
Ik heb awaitaan de bewering toegevoegd en het probleem is opgelost:

Voorbeeld met Cucumberjs:

Then(/I see heading with the text of Tasks/, async function() {
    await chai.expect('h1').dom.to.contain.text('Tasks');
});

Antwoord 8

Even een waarschuwing dat je een UnhandledPromiseRejectionWarningkunt krijgen als je per ongeluk je testcode buiten de it-functie plaatst. ??

   describe('My Test', () => {
      context('My Context', () => {
        it('should test something', () => {})
        const result = testSomething()
        assert.isOk(result)
        })
      })

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes