Chai: comment tester pour undefined avec la syntaxe 'should'

95

En me basant sur ce tutoriel testant une application angularjs avec chai, je souhaite ajouter un test pour une valeur indéfinie en utilisant le style "devrait". Cela échoue:

it ('cannot play outside the board', function() {
  scope.play(10).should.be.undefined;
});

avec l'erreur "TypeError: Impossible de lire la propriété 'should' of undefined", mais le test réussit avec le style "expect":

it ('cannot play outside the board', function() {
  chai.expect(scope.play(10)).to.be.undefined;
});

Comment puis-je le faire fonctionner avec "devrait"?

thebenedict
la source
1
C'est facile si vous utilisez "assert", vous pouvez le faire commeassert.isUndefined(scope.play(10))
lukaserat

Réponses:

80

C'est l'un des inconvénients de la syntaxe should. Cela fonctionne en ajoutant la propriété should à tous les objets, mais si une valeur de retour ou une valeur de variable n'est pas définie, il n'y a pas d'objet pour contenir la propriété.

La documentation propose des solutions de contournement, par exemple:

var should = require('chai').should();
db.get(1234, function (err, doc) {
  should.not.exist(err);
  should.exist(doc);
  doc.should.be.an('object');
});
David Norman
la source
14
should.not.existvalidera si la valeur est nulltelle que cette réponse n'est pas correcte. a la réponse @ Daniel ci - dessous: should.equal(testedValue, undefined);. Cela devrait être la réponse acceptée.
Sebastian
7
J'arrive à cette réponse (pas à la documentation 🙈) tous les mois :-)
Ralph Cowling
52
should.equal(testedValue, undefined);

comme mentionné dans la documentation chai

Daniel
la source
12
omg, qu'est-ce qu'il y a à expliquer? Vous vous attendez à ce que la valeur testée soit === undefined donc vous la testez. Beaucoup de développeurs mettent d'abord testingValue en premier, puis l'enchaînent avec should et cela se termine par une erreur ...
Daniel
5
Cela ne fonctionne pas immédiatement et ne se trouve pas dans la documentation de l'API pour.equal() . Je peux comprendre pourquoi @OurManInBananas a demandé une explication. C'est une utilisation inattendue de should en tant que fonction acceptant deux arguments, au lieu de la forme de méthode chaînée attendue acceptant un seul argument pour la valeur attendue. Vous ne pouvez y parvenir qu'en important / exigeant et attribuant une version invoquée de .should()comme décrit dans la réponse acceptée par @DavidNorman et dans cette documentation .
gfullam
Je pense que vous constaterez que cette .equalsyntaxe produit de bien meilleurs messages d'erreur car elle vous permet de générer des messages plus descriptifs lorsque les choses échouent
jcollum
17

Tester pour undefined

var should = require('should');
...
should(scope.play(10)).be.undefined;

Tester la valeur nulle

var should = require('should');
...
should(scope.play(10)).be.null;

Test de faux, c'est-à-dire traité comme faux dans des conditions

var should = require('should');
...
should(scope.play(10)).not.be.ok;
Peter Dotchev
la source
Pas particulièrement utile ou intuitif, mais c'est malin!
thebenedict
2
pas utile? C'est la meilleure réponse pour les tests non définis dans le style bdd IMO, mais il doit installer un autre package npm (le package should), et je ne pense pas que cela vaille la peine d'installer un autre package juste pour cela, réponse géniale cependant
Wagner Leonardi
16
(typeof scope.play(10)).should.equal('undefined');
teddychan
la source
8

J'ai eu du mal à écrire l'instruction should pour les tests non définis. Ce qui suit ne fonctionne pas.

target.should.be.undefined();

J'ai trouvé les solutions suivantes.

(target === undefined).should.be.true()

if peut également l'écrire comme un contrôle de type

(typeof target).should.be.equal('undefined');

Je ne sais pas si ce qui précède est le bon moyen, mais cela fonctionne.

Selon le message de fantôme dans github

Viraths
la source
1
Il convient de noter que l'utilisation de cette syntaxe peut entraîner l'interprétation par JavaScript de l'expression entre parenthèses comme une tentative d'appeler la ligne précédente en tant que fonction (si vous ne terminez pas les lignes par un point-virgule).
bmacnaughton
5

Essaye ça:

it ('cannot play outside the board', function() {
   expect(scope.play(10)).to.be.undefined; // undefined
   expect(scope.play(10)).to.not.be.undefined; // or not
});
EpokK
la source
Merci, mais c'est ce que je fais dans la deuxième tentative ci-dessus. J'aimerais comprendre comment le faire avec la syntaxe should .
thebenedict
1

La réponse de @ david-norman est correcte selon la documentation, j'ai eu quelques problèmes avec l'installation et j'ai plutôt opté pour ce qui suit.

(typeof scope.play (10)). should.be.undefined;

Andy Polhill
la source
typeofl'opérateur renvoie une chaîne ; donc cette assertion n'a pas pu être passée; cuz'undefined' !== undefined
dNitro
1

N'oubliez pas une combinaison de mots have- notclés et :

const chai = require('chai');
chai.should();
// ...
userData.should.not.have.property('passwordHash');
Yarovoy
la source
0

Vous pouvez encapsuler le résultat de votre fonction should()et tester un type "indéfini":

it ('cannot play outside the board', function() {
  should(scope.play(10)).be.type('undefined');
});
pegli
la source