web-dev-qa-db-fra.com

Vérifiez qu'une exception est générée à l'aide de Mocha/Chai et async/wait

J'ai du mal à trouver le meilleur moyen de vérifier qu'une promesse est rejetée dans un test Mocha lors de l'utilisation de async/wait.

Voici un exemple qui fonctionne, mais je n'aime pas que should.be.rejectedWith renvoie une promesse qui doit être renvoyée à partir de la fonction de test pour être correctement évaluée. L'utilisation de async/wait supprime cette exigence de test des valeurs (comme je le fais pour le résultat de wins() ci-dessous), et j'estime qu'il est probable que j'oublierai l'instruction de retour à un moment donné, auquel cas le test sera toujours réussi.

// Always succeeds
function wins() {
  return new Promise(function(resolve, reject) {
    resolve('Winner');
  });
}

// Always fails with an error
function fails() {
  return new Promise(function(resolve, reject) {
    reject('Contrived Error');
  });
}

it('throws an error', async () => {
  let r = await wins();
  r.should.equal('Winner');

  return fails().should.be.rejectedWith('Contrived Error');
});

Il me semble qu’il devrait être possible d’utiliser le fait que async/wait traduit les refus en exceptions et les combine avec ceux de Chai should.throw, mais je n’ai pas été en mesure de déterminer la syntaxe correcte.

Idéalement, cela fonctionnerait, mais ne semble pas:

it('throws an error', async () => {
  let r = await wins();
  r.should.equal('Winner');

  (await fails()).should.throw(Error);
});
8
plexer

Le problème avec cette approche est que (await fails()).should.throw(Error) n'a pas de sens.

await résout une Promise. Si Promise rejette, il renvoie la valeur rejetée.

Donc, (await fails()).should.throw(Error) ne peut jamais fonctionner: si fails() rejette, une erreur est générée et .should.throw(Error) n'est jamais exécuté.

L'option la plus idiomatique que vous avez est d'utiliser la propriété rejectedWith de Chai, comme vous l'avez montré dans votre question.

Voici un exemple rapide. Peu de choses sont différentes de ce que vous avez démontré dans votre question. J'utilise simplement les fonctions async pour wins() et fails() et expect au lieu de should. Bien sûr, vous pouvez utiliser des fonctions qui renvoient parfaitement une Promise et un chai.should.

const chai = require('chai')
const expect = chai.expect
chai.use(require('chai-as-promised'))

// Always succeeds
async function wins() {
  return 'Winner'
}

// Always fails with an error
async function fails() {
  throw new Error('Contrived Error')
}

it('wins() returns Winner', async () => {
  expect(await wins()).to.equal('Winner')
})

it('fails() throws Error', async () => {
  await expect(fails()).to.be.rejectedWith(Error)
})

Si vous voulez que votre test wins() ressemble plus à votre test fails(), vous pouvez écrire votre test wins() comme suit:

it('wins() returns Winner', async () => {
  await expect(wins()).to.eventually.equal('Winner')
})

L'essentiel à retenir dans l'un ou l'autre de ces exemples est que chai-as-promised renvoie des promesses pour ses fonctions telles que rejectedWith et eventually.something. Par conséquent, vous devez await les dans le contexte d'une fonction de test async, faute de quoi les conditions qui échouent seront toujours satisfaisantes:

async function wins() {
  return 'Loser'
}

async function fails() {
  return 'Winner'
}

it('wins() returns Winner', async () => {
  expect(wins()).to.eventually.equal('Winner')
})

it('fails() throws Error', async () => {
  expect(fails()).to.be.rejectedWith(Error)
})

Si vous avez exécuté les tests avec le code ci-dessus, vous obtiendrez ce qui suit:

$ npm test

> [email protected] test /home/vsimonian/code/mocha-chai-async
> mocha .



  √ wins() returns Winner
(node:13836) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rej
ection id: 1): AssertionError: expected 'Loser' to equal 'Winner'
(node:13836) [DEP0018] DeprecationWarning: Unhandled promise rejections are dep
recated. In the future, promise rejections that are not handled will terminate
the Node.js process with a non-zero exit code.
  √ fails() throws Error
(node:13836) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rej
ection id: 2): AssertionError: expected promise to be rejected with 'Error' but
 it was fulfilled with 'Winner'

  2 passing (11ms)

Comme vous pouvez le constater, les assertions du chai ont en réalité échoué, mais elles ont échoué dans le contexte d'une promesse selon laquelle personne, jamais, awaited ou catched. Donc, Mocha ne voit pas d’échec et marque les tests comme s’ils ont réussi, mais Node.js (dont le comportement va changer à l’avenir, comme indiqué ci-dessus) imprime les rejets non gérés au terminal.

8
Adaline Simonian

Ceci est ma solution pour le problème. 

    try {
        // here the function that i expect to will return an errror
        let walletid = await Network.submitTransaction(transaction)
    } catch (error) {
        //  assign error.message to ErrorMessage
        var ErrorMessage = error.message;
        //  catch it and  re throw it in assret.throws fn and pass the error.message as argument and assert it is the same message expected
        assert.throws(() => { throw new Error(ErrorMessage) },'This user already exists');
    }
    // here assert that ErrorMessage is Defined ; if it is not defined it means that no error occurs
    assert.isDefined(ErrorMessage);
0
TLEJMI