Frage

Ich versuche, einen Test für den Jasmine Test Framework zu schreiben, die einen Fehler erwartet. Im Moment bin ich mit einer Jasmin Node.js Integration von GitHub .

In meinem Node-Modul Ich habe den folgenden Code:

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

Jetzt versuche ich, einen Test zu schreiben, die diesen Fehler erwartet:

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

Ich habe auch versucht Error() und einige andere Varianten und kann einfach nicht herausfinden, wie es funktioniert.

War es hilfreich?

Lösung

sollten Sie eine Funktion in den expect(...) Aufruf werden vorbei. Der Code, den Sie haben sich hier:

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

versucht, tatsächlich Anruf parser.parse(raw) in einem Versuch, das Ergebnis in expect(...) zu passieren,

Versuchen Sie eine anonyme Funktion verwenden stattdessen:

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

Andere Tipps

Sie verwenden:

expect(fn).toThrow(e)

Aber wenn man einen Blick auf die Funktion Kommentar haben werden (erwartet ist string):

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) {

Ich nehme an, Sie wahrscheinlich es so schreiben soll (Lambda mit - anonyme Funktion):

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

Dies wird im folgende Beispiel bestätigt:

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

Douglas Crockford empfiehlt nachdrücklich, diesen Ansatz, statt mit "neuen Fehler werfen ()" (Prototyping Fahrt):

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

I Jasmins toThrow Matcher mit folgenden ersetzen, die Sie auf die Ausnahme Name Eigenschaft oder der Nachricht Eigenschaft können übereinstimmen. Für mich macht diese Tests einfacher zu schreiben und weniger spröde, wie ich folgendes tun:

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

und dann Test mit dem folgenden:

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

Auf diese Weise können Sie mir die Ausnahmemeldung zwicken später ohne Tests zu brechen, wenn das Wichtigste ist, dass es die erwartete Art von Ausnahme ausgelöst hat.

Dies ist der Ersatz für toThrow, die dies ermöglicht:

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;
};

Eine elegantere Lösung als eine anonyme Funktion zu schaffen, der einzige Zweck ist, ist eine andere zu wickeln, ist die Verwendung ES5 der bind Funktion. Die bind Funktion erzeugt eine neue Funktion, die, wenn sie aufgerufen wird, hat seinen this Stichwortsatz den bereitgestellten Wert mit einer gegebenen Sequenz von Argumenten jeden vorhergehenden bereitgestellt, wenn die neue Funktion aufgerufen wird.

Statt:

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

Bedenken Sie:

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

Die bind-Syntax ermöglicht es Ihnen, Testfunktionen mit unterschiedlichen this Werten, und meiner Meinung nach macht den Test besser lesbar. Siehe auch: https://stackoverflow.com/a/13233194/1248889

Wie bereits erwähnt, eine Funktion Bedarf bestanden toThrow werden, da es die Funktion ist, den Sie in Ihrem Test beschreibt: „Ich erwarte, dass diese Funktion x werfen“

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

Bei der Verwendung von Jasmin-Matcher auch eine der verwenden können folgendes, wenn sie die Situation anzupassen;

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

oder

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

Ich weiß, dass mehr Code, aber Sie können auch tun:

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

Für Coffee Liebhaber

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

Für alle, die noch könnten dieses Problem konfrontiert werden, für mich die entsandte Lösung nicht funktioniert haben und es hielt diesen Fehler zu werfen: Error: Expected function to throw an exception. Ich später erkennen, dass die Funktion, die ich erwartet hatte, einen Fehler zu werfen war eine Asynchron-Funktion und erwartete Versprechen abgelehnt werde und dann Fehler aus, und das ist, was ich in meinem Code zu tun:

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

und das ist, was ich in meinem Test habe und es funktionierte:

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');
                });
            }));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top