Ответ 1
Вы можете попробовать использовать конструкцию Chai throw
. Например:
expect(Constructor).to.throw(Error);
Используя Mocha, я пытаюсь проверить, вызывает ли конструктор ошибку. Я не смог сделать это, используя синтаксис ожидания, поэтому я хотел бы сделать следующее:
it('should throw exception when instantiated', function() {
try {
new ErrorThrowingObject();
// Force the test to fail since error wasn't thrown
}
catch (error) {
// Constructor threw Error, so test succeeded.
}
}
Возможно ли это?
Вы можете попробовать использовать конструкцию Chai throw
. Например:
expect(Constructor).to.throw(Error);
Использование библиотеки should.js с should.fail
var should = require('should')
it('should fail', function(done) {
try {
new ErrorThrowingObject();
// Force the test to fail since error wasn't thrown
should.fail('no error was thrown when it should have been')
}
catch (error) {
// Constructor threw Error, so test succeeded.
done();
}
});
Альтернативу вы можете использовать throwError
(function(){
throw new Error('failed to baz');
}).should.throwError(/^fail.*/)
И с помощью chai, используя throw api
var expect = require('chai').expect
it('should fail', function(done) {
function throwsWithNoArgs() {
var args {} // optional arguments here
new ErrorThrowingObject(args)
}
expect(throwsWithNoArgs).to.throw
done()
});
Теперь Chai имеет
should.fail()
и expect.fail()
Ответ 2017, если вам нужно сделать это с помощью асинхронного кода: использовать await и не требовать никаких других библиотек.
it('Returns a correct error response when making a broken order', async function(){
this.timeout(5 * 1000);
var badOrder = {}
try {
var result = await foo.newOrder(badOrder)
// The line will only be hit if no error is thrown above!
throw new Error('Expected an error and didn't get one!')
} catch(err) {
var expected = 'Missing required field'
assert.equal(err.message, expected)
}
});
Заметьте, что постер делал только код синхронизации, но я ожидаю, что многие люди, использующие асинхронный режим, приводят здесь заголовок вопроса!
Mocha по умолчанию использует Assert из node.js(https://nodejs.org/api/assert.html). Вам не нужны внешние библиотеки, чтобы проверить, вызывает ли метод ошибку.
У Assert есть метод - assert.throws
, он имеет три параметра, но здесь только два:
Предположим, что у вас есть функция с именем sendMessage(message)
, которая выдает ошибку, когда параметр сообщения не задан. Код функции:
function sendMessage(message) {
if (!message || typeof message !== 'string') {
throw new Error('Wrong message');
}
// rest of function
}
Хорошо, поэтому для его проверки вам нужна дополнительная функция для ввода ввода. Зачем? Поскольку assert.throws
не дает возможности передавать параметры функции, которая будет протестирована.
Итак, вместо
// WRONG
assert.throws(sendMessage, Error); // THIS IS WRONG! NO POSSIBILITY TO PASS ANYTHING
вам нужно создать анонимную функцию:
// CORRECT
assert.throws(() => {
sendMessage(12); // usage of wanted function with test parameters
}, Error)
Вы видите разницу? Вместо прямой передачи функции я поместил вызов функции внутри анонимной функции, чтобы вызвать ее с подготовленным вводом.
Как насчет второго параметра. Это зависит от того, какую ошибку следует выбросить, в приведенном выше примере Error
объект был брошен, поэтому мне пришлось поставить там Error
. В результате этого действия assert.throws
сравнивается, если брошенный объект является объектом того же типа. Если вместо Error
будет выбрано что-то другое, тогда эту часть нужно изменить. Например, вместо Error
я вывожу значение типа String
.
function sendMessage(message) {
if (!message || typeof message !== 'string') {
throw 'Wrong message'; // change to String
}
// rest of function
}
Теперь тестовый вызов
assert.throws(() => {
sendMessage(12); // usage of wanted function with test parameters
}, (err) => err === 'Wrong message')
Вместо Error
во втором параметре я использовал функцию сравнения, чтобы сравнить полученную ошибку с ожиданием.
Если вы используете should.js, вы можете сделать (new ErrorThrowingObject).should.throw('Option Error Text or Regular Expression here')
Если вы не хотите иметь отдельную библиотеку, вы также можете сделать что-то вроде этого:
it('should do whatever', function(done) {
try {
...
} catch(error) {
done();
}
}
Таким образом, вы знаете, что ошибка улавливается, если тест завершается. В противном случае вы получите ошибку тайм-аута.
Принятый MarkJ ответ - это путь, который намного проще, чем другие. Позвольте мне показать пример из реальной жизни:
function fn(arg) {
if (typeof arg !== 'string')
throw TypeError('Must be an string')
return { arg: arg }
}
describe('#fn', function () {
it('empty arg throw error', function () {
expect(function () {
new fn()
}).to.throw(TypeError)
})
it('non-string arg throw error', function () {
expect(function () {
new fn(2)
}).to.throw(TypeError)
})
it('string arg return instance { arg: <arg> }', function () {
expect(new fn('str').arg).to.be.equal('str')
})
})
С Chai throw
(ES2016)
http://chaijs.com/api/bdd/#method_throw
Для ясности... Это работает
it('Should fail if ...', done => {
let ret = () => {
MyModule.myFunction(myArg);
};
expect(ret).to.throw();
done();
});
Это не работает
it('Should fail if ...', done => {
let ret = MyModule.myFunction(myArg);
expect(ret).to.throw();
done();
});
Если вы не хотите, чтобы обернуть всю массу источника в expect
параметра, или если у вас есть много аргументов, чтобы пройти, и он просто становится уродливым, вы можете сделать это с помощью оригинального синтаксиса просто отлично за счет использования done
аргумент, при условии (но изначально был проигнорирован):
it('should throw exception when instantiated', function(done: Done) {
try {
new ErrorThrowingObject();
done(new Error('Force the test to fail since error wasn't thrown'));
}
catch (error) {
// Constructor threw Error, so test succeeded.
done();
}
}
Поскольку вы используете здесь done
, он позволяет вам выполнить произвольный код над ним при try
, а затем точно указать, где в вашем источнике вы хотите записать ошибку.
Как правило, кто - то может возникнуть соблазн throw
или assert(false)
, но они оба будут пойманы catch
в try
, и заставить вас сделать некоторые мета-проверки, чтобы определить, является ли ошибка, которую вы поймали была ожидаемая ошибка из теста или, если это было окончательное решение, что ваш тест не прошел. Это просто беспорядок.