Как написать тест, который ожидает, что ошибка будет брошена в жасмин?

StackOverflow https://stackoverflow.com/questions/4144686

Вопрос

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

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

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() И некоторые другие варианты и просто не могут понять, как сделать это работать.

Это было полезно?

Решение

Вы должны передавать функцию в 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"));

Другие советы

Ты используешь:

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");

Douglas Crockford настоятельно рекомендует этот подход, а не использовать «бросить новую ошибку ()» (путь прототипирования):

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

Я заменяю TOTHROW MACHOW JASMINE с помощью следующего, что позволяет соответствовать свойству имени исключения или свойство его сообщению. Для меня это облегчает тесты для записи и менее хрупких, так как я могу сделать следующее:

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

Более элегантное решение, чем создание анонимной функции, которая единственная цель, которая является обертывающей другой, это использовать ES5's bind функция. Функция BING создает новую функцию, которая, когда вызывается, имеет ее 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.

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

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

При использовании Жасмин-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);

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

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

Для любителей CoffeeScript

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

Для тех, кто все еще может столкнуться с этим вопросом, для меня размещенное решение не работало, и он продолжал бросать эту ошибку: 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');
                });
            }));
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top