Uncaught ReferenceError: как обрабатывать исключение, используя Chai [duplicate]

Если B:f не является виртуальным, то обе функции D:f будут плохо сформированы.

180
задан Yves M. 29 June 2015 в 12:04
поделиться

6 ответов

Вы должны передать функцию expect. Например:

expect(model.get.bind(model, 'z')).to.throw('Property does not exist in model schema.');
expect(model.get.bind(model, 'z')).to.throw(new Error('Property does not exist in model schema.'));

Как вы это делаете, вы переходите к expect результату вызова model.get('z'). Но чтобы проверить, что-то брошено, вам нужно передать функцию expect, которую expect будет вызывать сам. Используемый выше метод bind создает новую функцию, которая при вызове вызовет model.get с this, установленным на значение model, и первым аргументом, установленным на 'z'.

Хороший объяснение bind можно найти здесь .

236
ответ дан Louis 15 August 2018 в 20:47
поделиться
  • 1
    Я передал функцию, не так ли? Экземпляр model имеет функцию, называемую get, которую я передал / вызывал в ожидании. – doremi 5 February 2014 в 22:00
  • 2
    Нет, см. Объяснение, которое я добавил, когда вы писали свой комментарий. – Louis 5 February 2014 в 22:02
  • 3
    Уф. Почему docs ( chaijs.com/api/bdd/#throw ) демонстрируют это использование bind? Похоже, что наиболее распространенный сценарий тестирования для to.throw - это тестирование определенного условия внутри функции, которое требует вызова этой функции с недопустимым состоянием / аргументами. (В этом отношении .... почему бы не отключить chaijs.com deeplinks?) – ericsoco 19 August 2014 в 17:44
  • 4
    Когда вы передаете некоторые параметры, которые не следует бросать, тест все же остается. – Alexandros Spyropoulos 5 November 2014 в 01:08
  • 5
    @AlexandrosSpyropoulos Это не мой опыт, поэтому, пожалуйста, приведи пример случая, который иллюстрирует, что вы имеете в виду. – Louis 5 November 2014 в 01:09

Этот вопрос имеет много, много дубликатов, включая вопросы, не упоминающие библиотеку утверждения Chai. Вот основные сведения, собранные вместе:

Утверждение должно вызывать функцию, а не сразу оценивать.

assert.throws(x.y.z);      
   // FAIL.  x.y.z throws an exception, which immediately exits the
   // enclosing block, so assert.throw() not called.
assert.throws(()=>x.y.z);  
   // assert.throw() is called with a function, which only throws
   // when assert.throw executes the function.
assert.throws(function () { x.y.z });   
   // if you cannot use ES6 at work
function badReference() { x.y.z }; assert.throws(badReference);  
   // for the verbose
assert.throws(()=>model.get(z));  
   // the specific example given.
homegrownAssertThrows(model.get, z);
   //  a style common in Python, but not in JavaScript

Вы можете проверить наличие определенных ошибок с помощью любой библиотеки утверждений:

Узел

  assert.throws(() => x.y.z);
  assert.throws(() => x.y.z, ReferenceError);
  assert.throws(() => x.y.z, ReferenceError, /is not defined/);
  assert.throws(() => x.y.z, /is not defined/);
  assert.doesNotThrow(() => 42);
  assert.throws(() => x.y.z, Error);
  assert.throws(() => model.get.z, /Property does not exist in model schema./)

Должен

  should.throws(() => x.y.z);
  should.throws(() => x.y.z, ReferenceError);
  should.throws(() => x.y.z, ReferenceError, /is not defined/);
  should.throws(() => x.y.z, /is not defined/);
  should.doesNotThrow(() => 42);
  should.throws(() => x.y.z, Error);
  should.throws(() => model.get.z, /Property does not exist in model schema./)

Chai Expect

  expect(() => x.y.z).to.throw();
  expect(() => x.y.z).to.throw(ReferenceError);
  expect(() => x.y.z).to.throw(ReferenceError, /is not defined/);
  expect(() => x.y.z).to.throw(/is not defined/);
  expect(() => 42).not.to.throw();
  expect(() => x.y.z).to.throw(Error);
  expect(() => model.get.z).to.throw(/Property does not exist in model schema./);

Вы должны обрабатывать исключения, которые «выходят» из теста

it('should handle escaped errors', function () {
  try {
    expect(() => x.y.z).not.to.throw(RangeError);
  } catch (err) {
    expect(err).to.be.a(ReferenceError);
  }
});

Это может показаться запутанным вначале. Как ездить на велосипеде, он просто «нажимает» навсегда, как только нажимает.

39
ответ дан Charles Merriam 15 August 2018 в 20:47
поделиться

Как этот ответ говорит , вы также можете просто обернуть свой код анонимной функцией следующим образом:

expect(function(){
    model.get('z');
}).to.throw('Property does not exist in model schema.');
134
ответ дан Community 15 August 2018 в 20:47
поделиться
  • 1
    Это не работает для асинхронных вызовов функций. Предположим, что model.get является async, который возвращает обещание. Однако это порождает ошибку. Если я попробую вышеуказанный подход, это «Вывод времени». как мы должны уведомить "сделано" к мокке. В то же время я не могу попробовать expect(function(){ model.get('z'); }).to.throw('Property does not exist in model schema.').notify(done); Поскольку метода уведомления не существует. – Anand N 15 February 2015 в 13:53
  • 2
    @AnandN Если я понимаю вашу проблему, это звучит так, будто вам просто нужно реорганизовать свой код для обработки ошибки. Не будет ли необработанная ошибка в асинхронной функции проблемой в вашем реальном приложении? – twiz 18 April 2015 в 15:27
  • 3
    Спасибо twiz за ваш ответ. Мы работаем в интегрированной среде, модуль использования заботится о том, чтобы поймать исключения. Таким образом, проблема заключается в том, когда мы пытаемся запустить единичные тестовые примеры. Наконец, мы использовали подход ниже, чтобы заставить его работать catch (err) { expect(err).equal('Error message to be checked'); done(); } – Anand N 20 April 2015 в 07:58
  • 4
    Хорошее решение, за исключением случаев, когда вы используете this внутри вызываемой функции. Тогда .bind - правильный путь. – rabbitco 1 December 2016 в 16:21

И если вы уже используете ES6 / ES2015, вы также можете использовать функцию стрелки. Это в основном то же самое, что и обычная анонимная функция, но короче.

expect(() => model.get('z')).to.throw('Property does not exist in model schema.');
62
ответ дан Daniel T. 15 August 2018 в 20:47
поделиться

из doc ...;)

, потому что вы полагаетесь на этот контекст :

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

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

  • завершает вызов метода или функции внутри другой функции
  • связывает контекст
    // wrap the method or function call inside of another function
    expect(function () { cat.meow(); }).to.throw();  // Function expression
    expect(() => cat.meow()).to.throw();             // ES6 arrow function
    
    // bind the context
    expect(cat.meow.bind(cat)).to.throw();           // Bind
    
0
ответ дан Michal Miky Jankovský 15 August 2018 в 20:47
поделиться
0
ответ дан SeanOlson 29 October 2018 в 03:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: