Как написать тест, который ожидает, что ошибка будет выдана в Жасмин? - PullRequest
438 голосов
/ 10 ноября 2010

Я пытаюсь написать тест для Jasmine Test Framework , который ожидает ошибку. На данный момент я использую интеграцию Jasmine Node.js из GitHub .

В моем Node-модуле у меня есть следующий код:

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

Теперь я пытаюсь написать тест, который ожидает эту ошибку:

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

Я также попробовал Error() и некоторые другие варианты и просто не могу понять, как заставить это работать.

Ответы [ 8 ]

743 голосов
/ 10 ноября 2010

вы должны передать функцию в вызов expect(...). Код у вас здесь:

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

пытается вызвать parser.parse(raw), чтобы передать результат в expect(...),

Попробуйте вместо этого использовать анонимную функцию:

expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));
63 голосов
/ 10 ноября 2010

Вы используете:

expect(fn).toThrow(e)

Но если вы посмотрите на комментарий функции (ожидается строка):

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

Я полагаю, вам, вероятно, следует написать еговот так (используя лямбда-анонимную функцию):

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

Это подтверждается в следующем примере:

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

Дуглас Крокфорд настоятельно рекомендует такой подход, вместо использования «throw new Error»() "(прототип):

throw {
   name: "Error",
   message: "Parsing is not possible"
}
22 голосов
/ 05 февраля 2015

Более элегантное решение, чем создание анонимной функции, единственной целью которой является перенос другой, заключается в использовании функции es5 bind.Функция связывания создает новую функцию, для которой при вызове ее ключевое слово this устанавливается на предоставленное значение с заданной последовательностью аргументов, предшествующей любому предоставленному при вызове новой функции.

Вместо:

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

Рассмотрим:

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

Синтаксис привязки позволяет тестировать функции с различными значениями this, и, на мой взглядделает тест более читабельным.Смотри также: https://stackoverflow.com/a/13233194/1248889

22 голосов
/ 28 июля 2011

Я заменяю сопоставление toThrow от Jasmine на следующее, что позволяет сопоставить свойство name исключения или его свойство message.Для меня это облегчает написание тестов и делает их менее хрупкими, поскольку я могу сделать следующее:

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

, а затем выполнить тестирование со следующими параметрами:

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

Это позволяет мне настроить исключениесообщение позже, не нарушая тесты, когда важно то, что он выдал ожидаемый тип исключения.

Это замена toThrow, которая позволяет это:

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;
};
12 голосов
/ 24 января 2017

Как упоминалось ранее, функция должна быть передана на toThrow, так как это функция, которую вы описываете в своем тесте: «Я ожидаю, что эта функция сгенерирует x»

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

При использовании Jasmine-Matchers Вы также можете использовать одно из следующих действий, когда они соответствуют ситуации:

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

или

// I just want to know that an error of 
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
  .toThrowErrorOfType(TypeError);
8 голосов
/ 19 февраля 2014

Я знаю, что это больше кода, но вы также можете сделать:

try
   do something
   @fail Error("should send a Exception")
 catch e
   expect(e.name).toBe "BLA_ERROR"
   expect(e.message).toBe 'Message'
5 голосов
/ 15 февраля 2014

Для любителей кофе

expect( => someMethodCall(arg1, arg2)).toThrow()
1 голос
/ 15 февраля 2018

Для тех, кто все еще может столкнуться с этой проблемой, для меня опубликованное решение не сработало, и оно продолжало выдавать эту ошибку: Error: Expected function to throw an exception. Позже я понял, что функция, которую я ожидал выдать ошибку, была асинхроннойфункция и ожидал, что обещание будет отклонено, а затем выдать ошибку, и это то, что я делал в своем коде:

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

, и это то, что я сделал в своем тесте, и это сработало:

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');
                });
            }));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...