Question

Je suis en train d'écrire un test pour le cadre Jasmine test qui attend une erreur. En ce moment je suis sur un intégration Jasmine Node.js de GitHub.

Dans mon module Node je le code suivant:

throw new Error("Parsing is not possible");

Maintenant, je tente d'écrire un test qui attend cette erreur:

describe('my suite...', function() {
    [..]
    it('should not parse foo', function() {
    [..]
        expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
    });
});

J'ai essayé aussi Error() et quelques autres variantes et juste ne peut pas comprendre comment le faire fonctionner.

Était-ce utile?

La solution

vous devriez passer une fonction dans l'appel expect(...). Le code que vous avez ici:

// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));

tente de réellement Appel parser.parse(raw) pour tenter de passer le résultat dans expect(...),

Essayez d'utiliser à la place une fonction anonyme

expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));

Autres conseils

Vous utilisez:

expect(fn).toThrow(e)

Mais si vous avez un coup d'oeil sur le commentaire de la fonction (attendue est une chaîne):

294 /**
295  * Matcher that checks that the expected exception was thrown by the actual.
296  *
297  * @param {String} expected
298  */
299 jasmine.Matchers.prototype.toThrow = function(expected) {

Je suppose que vous devriez probablement écrire comme ça (en utilisant lambda - fonction anonyme):

expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");

Ceci est confirmé dans l'exemple suivant:

expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");

Douglas Crockford recommande fortement cette approche, au lieu d'utiliser "throw new Error ()" (mode prototypage):

throw {
   name: "Error",
   message: "Parsing is not possible"
}

Je remplace le matcher toThrow Jasmine avec ce qui suit, qui vous permet de matcher sur la propriété du nom ou sa propriété de message de l'exception. Pour moi, ce qui rend les tests plus faciles à écrire et moins fragile, comme je peux faire ce qui suit:

throw {
   name: "NoActionProvided",
   message: "Please specify an 'action' property when configuring the action map."
}

puis test avec les éléments suivants:

expect (function () {
   .. do something
}).toThrow ("NoActionProvided");

Cela me permet de bidouiller le message d'exception plus tard sans casser des tests, lorsque la chose importante est qu'il a jeté le type d'exception prévu.

est le remplacement de toThrow qui permet ceci:

jasmine.Matchers.prototype.toThrow = function(expected) {
  var result = false;
  var exception;
  if (typeof this.actual != 'function') {
    throw new Error('Actual is not a function');
  }
  try {
    this.actual();
  } catch (e) {
    exception = e;
  }
  if (exception) {
      result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected));
  }

  var not = this.isNot ? "not " : "";

  this.message = function() {
    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
      return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' ');
    } else {
      return "Expected function to throw an exception.";
    }
  };

  return result;
};

Une solution plus élégante que la création d'une fonction anonyme qui est le seul but est d'envelopper une autre, est d'utiliser ES5 bind fonction. La fonction de liaison crée une nouvelle fonction qui, lorsqu'elle est appelée, a son ensemble de mots-clés this à la valeur fournie, avec une séquence donnée d'arguments précédents quelconque pourvu que la nouvelle fonction est appelée.

Au lieu de:

expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");

Considérez:

expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");

La syntaxe de liaison permet à des fonctions de test avec des valeurs différentes de this, et à mon avis rend le test plus lisible. Voir aussi: https://stackoverflow.com/a/13233194/1248889

Comme mentionné précédemment, a besoin de fonction pour être transmis à toThrow car il est la fonction que vous décrivez dans votre test: «J'attends cette fonction pour lancer x »

expect(() => parser.parse(raw))
  .toThrow(new Error('Parsing is not possible'));

Si vous utilisez Jasmine-Matchers vous pouvez également utiliser l'un des suivant quand ils conviennent la situation;

// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
  .toThrowAnyError();

ou

// I just want to know that an error of 
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
  .toThrowErrorOfType(TypeError);

Je sais que plus le code, mais vous pouvez aussi le faire:

try
   do something
   @fail Error("should send a Exception")
 catch e
   expect(e.name).toBe "BLA_ERROR"
   expect(e.message).toBe 'Message'

Pour les amateurs CoffeeScript

expect( => someMethodCall(arg1, arg2)).toThrow()

Pour toute personne qui pourrait encore faire face à ce problème, pour moi la solution arrêtée ne pas de travail et il a continué à jeter cette erreur: Error: Expected function to throw an exception. Plus tard, je compris que la fonction que je comptais jeter une erreur est une fonction et async attendais promesse d'être rejetée puis jeter erreur et que ce que je faisais dans mon code:

throw new Error('REQUEST ID NOT FOUND');

et c'est ce que je faisais dans mon test et ça a marché:

it('Test should throw error if request not found', willResolve(() => {
         const promise = service.getRequestStatus('request-id');
                return expectToReject(promise).then((err) => {
                    expect(err.message).toEqual('REQUEST NOT FOUND');
                });
            }));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top