Is it possible to wrap chai.js expect functions to catch exceptions? - javascript

I want to use the chai.js expect assertions to perform multiple tests in my code.
If a assertion is failing I want to log it and then proceed with the next one.
e.g.>
expect(recvRequest.request.response.statusCode).to.equal(expResponse.statusCode);
expect(recvRequest.request.response).to.have.property(headers);
etc.
I want to be able to write multiple expects without encapsulating each one in a try catch. So I thought I write a simple wrapper for it but it failed.
I get an error at func.call
function exWrapper(func, arg) {
try {
func.call(null, arg);
} catch (e) {
return false;
}
return true;
}
exWrapper(expect(recvRequest.request.response.statusCode).to.equal, 120);
But during execution I get a: TypeError: this.assert is not a function
at assertEqual
I checked with a typeof and expect().to.equal is a function so what am I doing wrong?
I hope somebody can help me.
Regards
Ruvi

Related

Is there any way to break out of a function by running another function in JS

I am working on a simple project and I would like to create a simple helper function that checks for a error in a callback. If there is a error then it should break the whole function that called it. Code example:
//Makes call to database and tries to insert element
db.collection("data").insertOne(
{
key: 'some-data'
}, (error, result) => {
//Return error if something goes wrong - else error is empty
checkError(error, "Unable to load database");
console.log("Succes item added")
}
);
Note: Yes this is node.js but this whole principle could be repeated in js with other callbacks - very simple repeatable error principle.
So in the insertOne function the first argument is some data I am adding to the database. The second argument is the callback function that is called after this async operation is finished. It returns a error which I could just handle by adding this if statement to the callback:
if (error) {
console.error(error);
return;
}
Buuut thats disrespecting the dry principle (bc I write the exact same if statement everywhere with no syntax being changed except the message) and is also distracting when reading the callback function. Now my issue is in the function checkError() even tho I can just print the error with the message or throw the error, I dont actually have a way to break the original callback so that it doesnt cause any more havoc in my database. I will go on to promisify this callback which is a solution. BUT I want to know if there is a way to this in the way I presented it here. Note: I dont want to use the try catch block bc thats replacing a if statement with another two blocks.
My checkError function:
const checkError = function (error, msg = "Something went wrong") {
if (error) console.error(`${msg}: error`);
//Break original block somehow ¯\_(ツ)_/¯
};
If I were to compress my question it would be: how to break a function with another function. Is there any way to achieve this?
I don't think this is possible. But you could achieve something similar with this:
function checkError (error, msg = "Something went wrong") {
if (!error) return false;
console.error(`${msg}: error`);
return true;
};
db.collection("data").insertOne(
{
key: 'some-data'
}, (error, result) => {
//Return error if something goes wrong - else error is empty
if (checkError(error, "Unable to load database")) return;
console.log("Succes item added")
}
);
Things become easier when you use promises.
Often asynchronous APIs provide a promise interface, and this is also the case for mongodb/mongoose, where you can chain a .exec() call to execute the database query and get a promise in return. This gives you access to the power of JavaScript's async/await syntax. So you can then do like this:
async function main() {
// Connect to database
// ...
// Other db transactions
// ...
let result = await db.collection("data").insertOne({ key: 'some-data'}).exec();
console.log("Item added successfully");
// Any other database actions can follow here using the same pattern
// ...
}
main().catch(err => {
console.log(err);
});
The idea here is that await will throw an exception if the promise returned by .exec() eventually rejects. You can either put a standard try...catch construct around it to deal with that error, or you can just let it happen. In the latter case the promise returned by the wrapping async function will reject. So you can deal with the error at a higher level (like done above).
This way of working also removes the need for numerous nested callbacks. Often you can keep the nesting to just one of two levels by using promises.

Mocha await/async handling (expected) errors

Some time ago I was curious on how to execute async tests using Mocha and those tests to expect an error as a result (see Mocha async test handle errors)
Now I tried the same for the newer version of nodejs using await/async. Just a simple case but as I need to wrap the code in a try / catch block, things get out of hand.
After long hours of testing I ended up with a solution but it doesn't look good.
So I'm looking for a better way to do this.
The test looks like this:
it('myTest', async function () {
// THIS WORKS => CODE OPTION 1:
// this works, it uses promises but not await/async
return somePromiseFunction()
.then(() => Promise.reject(new Error('Expected method to reject.')))
.catch(err => assert.ok(err instanceof Error, 'This should be an error!'));
// THIS WORKS => CODE OPTION 2:
// this works, it uses await/async
let forceFail = false;
try {
await somePromiseFunction();
forceFail = true;
} catch (err) {}
if (forceFail) assert.ok(false, 'Expected method to reject.');
// WONT WORK => CODE OPTION 3:
try {
await somePromiseFunction();
assert.ok(false, 'you shouln\'t be here');
} catch (err) {
assert.ok(err instanceof Error, 'This should be an error!');
}
});
Both option 1 and 2 work. Option 1 uses classic Promise.then.catch syntax, and that's ok. Option 2 was the only way for me to make things work but is very complex to understand / maintain. It relies on a sort of global variable and handling states, and it just doesn't look good.
There is an option 3 in the code, but it does not work. Something like that would be easy to read but it does not work at all, not the first assert nor the second one.
If you remove the try / catch block then it won't work either.
Thanks.
In the third option, err would always be undefined since you're catching the exception as e, not as err. And the assert would always fail because undefined is not an instance of Error.
I found a way, but you'll need to upgrade to node version 10. I was using 8, but this new feature included in assert solves my problem in an elegant way.
Instead of trying this:
// WONT WORK => CODE OPTION 3:
try {
await somePromiseFunction();
assert.ok(false, 'you shouln\'t be here');
} catch (err) {
assert.ok(err instanceof Error, 'This should be an error!');
}
Do this:
// this works!
await assert.rejects(
async () => somePromiseFunction(),
Error
);
You can also verify the type of error being thrown, but in my case Error will suffice.
EDIT: async () => was not really necessary, I ended up with a one line assert (second parameter is optional, but I'd rather keep it):
await assert.rejects(somePromiseFunction(), Error);

Uses of the finally statement

This is a very basic question. In Java I use the finally statement to close resources because "it's a good practice". I've been developing in Javascript and then in Node.js during some years and I've never used the finally statement. I know that in Node.js all of us follow the first parameter error handling pattern. Anyway, the 2 following snippets do the same:
try{
throw 123
}catch (e){
}finally{
console.log(1)
}
.
try{
throw 123
}catch (e){
}
console.log(1)
Both print 1.
Why is finally a keyword if it has no real benefit? The clean up code can be put inside the catch.
finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break.
Just a simple and straightforward example that shows the difference. There is a return that breaks the function completion, but the console.log in finally is called while the last console.log is skipped.
let letsTry = () => {
try {
// there is a SyntaxError
eval('alert("Hello world)');
} catch(error) {
console.error(error);
// break the function completion
return;
} finally {
console.log('finally')
}
// This line will never get executed
console.log('after try catch')
}
letsTry();
But try this:
try {
throw "foo"
} catch (e) {
throw "bar"
} finally {
console.log("baz")
}
console.log("quux")
If a second error is thrown from within the catch block, the code after the try...catch block will not run.
The finally block will always run, even if there is an error in the catch block.
Furthermore, the finally block runs even if a return or break statement stops the code in the try or catch block. return statements in the finally block override return statements in the try or catch block.
function foo() {
try {
return "bar";
} finally {
return "baz";
}
}
foo() // "baz"
oracle docs provide a good answer to this. Bottom line: finally gets called always! Even when you catch only one kind of exception (not the global catch), then finally gets called (after which your application probably breaks if there is no other catch)
the finally block is meant for a special purpose.
finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.
Since it wont effect your business logic,Still it's compiler friendly,In memory aspects.
What if the try-block returns early or throws an exception that you don't handle? You would still want to free the resources you have allocated, right?
EDIT:
The answers to the question seem almost philosphical, there is some 'guessing' and basically 'we believe it should be useful, because it is there, so it should have a use', and 'even Oracle says so'. Or maybe it is there to help the programmer not 'to forget something' or 'accidently exit and not realize it'.
These are almost all valid reasons, but there is also a technical reason.
It helps avoiding code duplication in the cases mentioned, where (a) either the try or one of the catch blocks returns or (b) if within the catch block a second exception is thrown.
In these cases, if some cleanup code or any other code that still needs to be executed after the return and after the second exception, could be placed into the finally block, if it is to be executed both after the try and after the catch block.
You could still do it without the finally block, but the code would have to be duplicated, which the finally block allows you to avoid. This is where you really need it.
So if you are sure you do not miss it as a case of (a) or (b) you could still put the 'finally' code after the try/catch block and omit the finally clause.
But what if the situation changes? When you or another person change the code at some later point it could be forgotten to check if the cleanup code is now skipped in some situation.
So why not always put the cleanup code inside the finally block? And this is what is recommended and what many JavaScript programmers do.
You use it when you want to be sure your code is executed at the end, even if there was an exception during execution :
InputStream is = new FileInputStream("C://test.txt");
try {
//code...
} catch (Exception e) {
//code...
} finally {
is.close();
}
This is a very good question.
There is little to no reason to use finally in javascript, but I can imagine situations where it could be of practical use.
Suppose you have a webpage where you show a certain div after some user action, e.g. button clicked.
The div shows some logging for instance for the action the user requested.
After the action is complete (error or no error), you want to be sure to hide the div again. For that you can use the finally clause.
function doSomething() {
var d = document.getElementById("log");
show(d);
try {
... execute action ...
} catch(e) {
log(e);
} finally {
hide(d);
}
}
In general, as you mentioned, exceptions are less and less used in JavaScript in favor of error callbacks.
So, one could as well ask, what good uses are for exceptions in JavaScript in general.
The problem is with your example. There are cases when you don't want to catch the exception.
try {
if (Math.random() > 0.5) throw 123
}
finally {
console.log(1)
}
In these cases all you could do is rethrowing the exception if you don't want to use finally.
try {
if (Math.random() > 0.5) throw 123
}
catch (e) {
console.log(1)
throw e
}
console.log(1)
or maybe
try {
if (Math.random() > 0.5) throw 123
console.log(1)
}
catch (e) {
console.log(1)
throw e
}
Both alternative solutions lead to code duplication, that's why you need the finally keyword. It is used most of the time to free up unused resources. Forgetting about it may lead to unwanted locks or connections or memory leaks. I guess in some cases even a smart GC cannot prevent it.
In Java, if there's an Exception thrown that is not matched by any of the catch-blocks execution will break and any open resources will be left open.
The finally block will always be executed, even if an uncaught exception occurs.

Javascript error stops code execution

Whenever an error occurs inside an event handler, it stops code execution entirely so the second event callback isn't called.
For example:
$(function() {
window.thisDoesntExist();
}
$(function() {
//Do something unharmful and unrelated to the first event
}
You can easily solve the problem in this (simplified) example by adding try/catch in both anonymous functions, but in reality these functions often add several other event handlers which in turn would require try/catch. I end up with very repetitive code stuffed with try/catch blocks.
My projects has a modular design where each feature is in a different JS (and gets concatenated during a build process). I'm looking for a more generic way to handle errors inside each feature so that the error doesn't stop code execution of the other features.
I already tried following solutions:
- window.onerror (even if you return true in this function, code execution is stopped)
- $(window).error() => deprecated and code execution stops
You could create a helper function to prevent duplication of the same boilerplate code.
function tryFunction(f, onerror) {
try {
if (typeof f == 'function') {
return f();
}
} catch (e) {
return onerror(e);
}
}
$(function() {
var result = tryFunction(window.thisDoesNotExist, function (error) {
alert('Whoops: ' + error);
});
});
I created a little demonstration. It's slightly different but the same idea.
You can simply call if (typeof myFunction == 'function') before calling myFunction()
And optionally wrap it in a generic function like said by Bart to have the choice to log an error in the console if your function does not exists.
If your webapp is huge with many interaction and JS, too many try catch could alter the global performance of your application.
I would try something like this with a wrapper which will handle the try catch for you (see below, or this jsfiddle : http://jsfiddle.net/TVfCj/2/)
From the way I'm (not, and not really) handling the this and the arguments, I guess it's obvious I'm beginning with js. But I hope you get the idea, and it is correct/useful.
var wrapper = {
wrap: function wrap(f) {
return function (args) {
try {
f.apply(null, args);
} catch (ex){
console.log(f.name+" crashed with args "+args);
};
};
}
};
var f1 = function f1Crashes(arg) {
return window.thisDoesntExist();
};
var f2 = function f2Crashes(arg) {
return window.thisDoesntExist();
};
var f3 = function f3MustNotCrash(arg) {
wrapper.wrap(f1)(arg);
wrapper.wrap(f2)(arg);
}
f3('myarg');
The try-catch pattern you mention attempting in your question is the correct way - you want try-catch blocks, not a way to silently truck through module errors (in general always be extremely careful handling exceptions globally and continuing, that way lies data corruption bugs you only find 6 months later).
Your real problem is this:
... in reality these functions often add several other event handlers which in turn would require try/catch. I end up with very repetitive code stuffed with try/catch blocks.
The fix for that is Promise. This is a new structure, native in most browsers but easily shimmed in the slow ones (ahem, IE), that gives you a standard way of managing both the event callback and the exception from the event.
With a Promise your code makes a promise to always do something: either resolve/succeed or reject/fail.
function moduleA() {
return new Promise(function (resolve, reject)
{
try{
var result = window.thisDoesntExist();
resolve(resolve); // Success!
}
catch(err){
reject(err); // Fail!
}
});
}
This is better because rather than nest try-catch blocks in each callback you can instead chain promises:
moduleA().
then(moduleB).
then(moduleC).
catch(errorHandler); // Catch any error from A, B, or C
You can also handle an error and continue:
moduleA().
catch(continuableErrorHandler). // Catch any error from A
then(moduleB).
then(moduleC).
catch(errorHandler); // Catch any error from B or C
You'll still need lots of try-catch blocks in callbacks, but anything that has been wrapped in a Promise can be treated in the same modular way.
Coming next in JS is async and await, but you can use them now with a transpiler. These use promises to make code that is much easier to read, and most importantly (for you) have a single try-catch at the top that gathers exceptions from the entire Promise chain.
This answer is already too long, but I've blogged about that in more detail.
TL;DR: If your problem is "very repetitive [event callback] code stuffed with try/catch blocks" try using Promise instead.
I found a solution. When using setTimeout, the code is executed in a seperate thread, therefor it won't break any other parts of the webpage.
$(function() {
setTimeout(function() {
window.thisDoesntExist();
}, 0);
});
$(function() {
setTimeout(function() {
//Do something unharmful and unrelated to the first event
alert("This passes")
}, 0);
});
In this example, the second function is run, even when the first one throws an error.
Here's a working example: http://jsfiddle.net/mathieumaes/uaEsy/

JavaScript Catching exception from within function or object

I encountered quite annoying problem. I can't catch errors thrown from within the functions. And to be honest - I wouldn't care much if not the fact that the same applies for throwing errors from within the JavaScript Objects.
Here's the sample code:
http://jsfiddle.net/TxsHK/1/ (you'll need firebug console to test this code)
function ViewError($CONTENT){
this.content = $CONTENT;
return this.content;
};
try{
$(document).ready(function() {
//--------------
throw ViewError('Test error');
//--------------
});//$(document).ready(function() {
}catch (e) {
if (e instanceof ViewError) {
console.info(e.message);
}
else{
console.warn(e.message);
}
}
gives an error
TypeError: e is undefined
Why? The errors thrown by functions (or objects) should be perfectly catchable. That's the whole purpose of try - catch block: to catch exceptions out of functions. At least... so it is in other languages.
Anyone can explain what's going on? And how can I catch exceptions from within the functions / objects?
Your "ViewError" function doesn't return anything. You're therefore throwing undefined. (edit — your fiddle is diffferent from the posted code - don't do that!)
The "ViewError" function is being called in a way that I don't think to be correct, given the way the code is written. I think you want throw new ViewError("Test error"); in order to make sure a new object is created.
There's another problem: you're expecting that you'll be able to catch exceptions thrown from that call to $(document).ready(), but that's not necessarily going to work. If the document isn't ready yet when that code runs, then you'll get no exceptions because the call returns immediately. The function you pass in would be called later, when the document is ready.

Categories

Resources