Мокка/Чай ожидают, что не поймают заброшенные ошибки

У меня возникают проблемы с получением Chai expect.to.throw для работы в тесте для моего приложения node.js. Тест продолжает терпеть неудачу при сброшенной ошибке, но если я завершу тестовый пример в попытке и поймаю и утвержу на пойманной ошибке, он будет работать.

Не работает ли expect.to.throw, как я думаю, это должно или что-то еще?

it('should throw an error if you try to get an undefined property', function (done) {
  var params = { a: 'test', b: 'test', c: 'test' };
  var model = new TestModel(MOCK_REQUEST, params);

  // neither of these work
  expect(model.get('z')).to.throw('Property does not exist in model schema.');
  expect(model.get('z')).to.throw(new Error('Property does not exist in model schema.'));

  // this works
  try { 
    model.get('z'); 
  }
  catch(err) {
    expect(err).to.eql(new Error('Property does not exist in model schema.'));
  }

  done();
});

Ошибка:

19 passing (25ms)
  1 failing

  1) Model Base should throw an error if you try to get an undefined property:
     Error: Property does not exist in model schema.

Ответ 1

Вам нужно передать функцию 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 можно найти здесь.

Ответ 2

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

expect(function(){
    model.get('z');
}).to.throw('Property does not exist in model schema.');

Ответ 3

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

expect(() => model.get('z')).to.throw('Property does not exist in model schema.');

Ответ 4

У этого вопроса много, много дубликатов, включая вопросы, не упоминающие библиотеку утверждения 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

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

Node

  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

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

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