In my mocha testframework, I have an it-block that might throw an error. How do I obtain this error in the afterEach-hook that is called afterwards? Is there any workaround if it is not directly passed?
...
afterEach(async function () {
var testObject = {
title: this.currentTest.title,
state: this.currentTest.state,
duration: this.currentTest.duration,
timedOut: this.currentTest.timedOut,
error: this.currentTest.err // I want the error object here
}
});
it('my title', () => {
try {
doSomethingThatMightThrowError();
} catch (err) {
throw new Error(err)
}
});
....
Related
I m trying to write unit test cases to handle error codes that are defined below. not sure how to achieve it.
module.exports = {
Error: Err,
BadRequest: function () {
return new Err(400, 'Bad Request');
},
NotAcceptable: function () {
return new Err(406, 'Not Acceptable');
},
NotAuthorized: function () {
return new Err(401, 'Not Authorized');
}
};
function Err(code, message) {
assert(code, 'code');
Error.call(this);
Error.captureStackTrace(this, this.constructor);
Object.defineProperty(this, 'code', {
enumerable: true,
value: code
});
this.reason = message;
}
You should have a better base error layer by extending the Error class which already provide most of the functions you would need (capturing the stack trace automatically):
class Err extends Error {
constructor(code, message) {
super(message);
this.code = code;
this.reason = message;
}
}
You can then performa your assertion using the throw expectation:
const errorFn = () => { throw new Err(401, 'Unauthorized') };
expect(errorFn).to.throw(Err).to.haveOwnProperty('code', 401).to.haveOwnProperty('reason', 'Unauthorized');
You should obviously update your sub-error accordingly to extend your generic error.
I am getting the following error (it won't even get to the console.log part of my code):
ERROR error in cloudinary module Cannot convert undefined or null to object 09:05:40
at Function.keys (<anonymous>)
at setSignature (modules\cloudinary\index.js:15:14)
Here is my code:
modules/cloudinary/index.js:
export default function () {
this.nuxt.hook('render:setupMiddleware', (app) => {
app.use('/api/cloudinary/signature', setSignature)
})
function setSignature(req, res) {
try {
const payload = []
Object.keys(req.body).forEach((key) => {
payload.push(`${key}=${req.body[key]}`)
})
console.log(payload)
} catch (error) {
console.error('error in cloudinary module', error)
}
}
}
Something going on with the Object here. Anyone spot anything?
Updated:
Doing the following console.log gives me undefined on the req.body:
export default function () {
// const config = this.options.privateRuntimeConfig.cloudinary
this.nuxt.hook('render:setupMiddleware', (app) => {
app.use('/api/cloudinary/signature', setSignature)
})
function setSignature(req, res) {
try {
console.log(req.body)
How can I use this inside a callback? Using callback, I got undefined on this.callback() (this is undefined):
constructor(collection, journey, callback, environment=null) {
this.collection = collection;
this.journey = journey;
this.callback = callback;
console.log(this.callback)
this.environment = environment;
}
run() {
newman.run({
collection: this.collection,
environment: this.environment,
insecure: true
}, this.internalCallback).on('console', function (err, args) {
console.log(args.messages.join(' '));
})
}
internalCallback(error, summary) {
if(error || summary.error) throw (error || summary.error)
console.log(this)
this.callback(this.journey, summary) // here throws an error because this is undefined
}
I assume that newman.run creates a new "this" context in your code. Have you tried binding the function: this.internalCallback.bind(this) to this of your class when passing it to newman.run?
Try this code:
run() {
newman.run({
collection: this.collection,
environment: this.environment,
insecure: true
}, this.internalCallback.bind(this)).on('console', function (err, args) {
console.log(args.messages.join(' '));
})
}
Can you try something like this:
that = this;
constructor(){
}
internalCallback(error, summary) {
if(error || summary.error) throw (error || summary.error)
console.log(this)
that.callback(that.journey, summary) // here throws an error because this is undefined
}
How to build an Error object instead of give its a string? https://codesandbox.io/s/pwr973487x
async function getUrl() {
try {
const res = await axios.get('https://httpstat.us/500')
} catch(e) {
const errorObj = {
status: 500,
message: 'Internal server error, something is not defined etc'
}
throw new Error('err') //how to build object?
}
}
I want throw Error() to return errorObj. Do I have to do my own class to do that or I can modify the existing Error class for that? I need that so it standardize my error message of my different set of Apis.
You can use the error object returned from catch
try {
const res = await axios.get('https://httpstat.us/500')
} catch(e) {
e.message = 'Internal server error, something is not defined etc';
throw e;
}
You can just add a field to the Error object, e.g.
var err = new Error('Internal Server error');
err.customField = { someProperty: 'some value'};
console.log(err);
And then you can throw it as normal:
throw err;
When you catch the error (higher up in the call stack) you can pull out the custom field:
try
{
throw err;
}
catch (e)
{
console.error(e);
console.log(e.customField);
}
With ES6 onwards you can also create your own error class:
class MyError extends Error {
constructor(message, customValue) {
super(message);
this.field = customValue;
}
get customField() {
return this.field;
}
set customField(obj) {
this.field = obj;
}
};
var ex = new MyError('Error message', {someProperty: 'some value'});
console.dir(ex);
console.log('My custom error details: ', ex.customField);
you could try with the cause propoty of :
TS has inaccurate value type about it at present, this is being discussed on the official to revolve it.
try {
throw new Error('Failed in some way', {
cause: {status: 400}
});
} catch(e) {
console.log(e); // Error('Failed in some way')
console.log(e.cause) // {status: 400}
}
or throw the Error instance with the custom property
try {
const error = new Error('Failed in some way');
error.status = 400;
throw error;
} catch(e) {
console.log(e); // Error('Failed in some way')
console.log(e.status) // 400
}
I my Node backend have the following end-point:
usersRoute.get('/get', function(req, res) {
//If no date was passed in - just use todays date
var date = req.query.date || dateFormat(new Date(), 'yyyy-mm-dd'),
search = req.query.search;
users.getAllUsers(date, search)
.then(function(results) {
res.json(results);
}, function(err) {
res.status(500).json({
success: false,
message: 'Server error.',
data: []
});
});
});
I have changed my sql table name to something else to trigger the function(err){} part
When I use this in my service it looks like this:
function getUsers(date, search) {
return $http.get('/api/users/get', {
params: {
date: UtilsService.formatDate(date),
search: search
}
})
.then(getData)
.catch(handleErr);
function getData(response) {
return response.data;
}
function handleErr(err) {
LoggerService.error('Could not retrieve users.', err ,'Ooops');
}
}
Knowing the server will return an http status code 500, I thought it would go right to the catch block. But it also returns the data /which is undefined in the then block
I use my service in my controller like this:
function getUsers(date, search) {
isAdmin();
vm.loading = true;
vm.filteredUsers = [];
return UsersService.getUsers(date, search).then(function(data) {
vm.loading = false;
allUsers = data || [];
vm.filteredUsers = allUsers.slice(0, 50);
vm.distribution = UsersService.getDistribution(allUsers);
return vm.filteredUsers;
});
}
My problem is, since the then part is triggered in my service. I'm trying to slice undefined
My question is: What are som best practices when it comes to this sort of pattern.
The problem is that your catching the error from your API and then returning the promise created by .catch.
Quick example
promise.then(function(data) {
throw 'Some error';
}).catch(function (err) {
console.log(err) // will output 'Some error'
}).then(function () {
// This will run even though we have a catch before
});
So how can we prevent the .then it's easy we throw an error inside the .catch
promise.then(function(data) {
throw 'Some error';
}).catch(function (err) {
console.log(err) // will output 'Some error'
throw 'You shall not pass'
}).then(function () {
// This will not run
});
So in your case you have two options, one throw an error as I said or two inject the $q service into your service:
function getUsers(date, search) {
return $http.get('/api/users/get', {
params: {
date: UtilsService.formatDate(date),
search: search
}
})
.then(getData)
.catch(handleErr);
function getData(response) {
return response.data;
}
function handleErr(err) {
LoggerService.error('Could not retrieve users.', err ,'Ooops');
return $q.reject(err);
}
}
You could do something like that
function getUsers(date, search, cb) {
return $http.get('/api/users/get', {
params: {
date: UtilsService.formatDate(date),
search: search
}
})
.then(cb)
.catch(handleErr);
function handleErr(err) {
LoggerService.error('Could not retrieve users.', err ,'Ooops');
}
}
And then in your controller
UsersService.getUsers(date, search, function(data) {
vm.loading = false;
allUsers = data || [];
vm.filteredUsers = allUsers.slice(0, 50);
vm.distribution = UsersService.getDistribution(allUsers);
});