Sequelize Tests - Sometimes Validation Error - javascript

I'm running unittests via Mocha / Chai on a sequelize definition as shown:
Main tests.js that is run with mocha tests.js:
// Testing Dependencies
expect = require("chai").expect;
should = require("chai").should;
require('dotenv').load();
var Sequelize = require('sequelize');
var sequelize = new Sequelize(
process.env.PG_DB_TEST,
process.env.PG_USER,
process.env.PG_PASSWORD, {
dialect: "postgres",
logging: false
});
var models = require('./models/db')(sequelize);
var seq_test = function (next) {
return function () {
beforeEach(function (done) {
sequelize.sync({ force: true }).then(function() {
done();
});
});
afterEach(function (done) {
sequelize.drop().then(function() {
done();
});
});
next();
};
}
describe("Model Unittests", seq_test(function () {
require("./models/tests/test_user.js")(models);
require("./models/tests/test_interest.js")(models);
}));
test_user.js
var mockedUser = require("./mocks/user");
module.exports = function (models) {
var User = models.user;
it("User should have the correct fields", function (done) {
User.create(mockedUser).then(function (result) {
expect(result.pack()).to.include.all.keys(
["id", "name", "email", "intro"]
);
done();
});
});
it("User should require an email", function (done) {
User.create({
"name": mockedUser['name']
}).then(function (result) {
expect.fail();
done();
}).catch(function (err) {
expect(err['name']).to.be.equal('SequelizeValidationError');
done();
});
});
it("User should require a name", function (done) {
User.create({
"email": mockedUser['email']
}).then(function (result) {
expect.fail();
done();
}).catch(function (err) {
expect(err['name']).to.be.equal('SequelizeValidationError');
done();
});
});
}
Sometimes (about 1 out of 15 on a Codeship (CI)), it gives this error:
Model Unittests
Unhandled rejection SequelizeUniqueConstraintError: Validation error
at Query.formatError (/home/rof/src/github.com/podtogether/pod-test-prototype/node_modules/sequelize/lib/dialects/postgres/query.js:402:16)
at null.<anonymous> (/home/rof/src/github.com/podtogether/pod-test-prototype/node_modules/sequelize/lib/dialects/postgres/query.js:108:19)
at emitOne (events.js:77:13)
at emit (events.js:169:7)
at Query.handleError (/home/rof/src/github.com/podtogether/pod-test-prototype/node_modules/pg/lib/query.js:108:8)
at null.<anonymous> (/home/rof/src/github.com/podtogether/pod-test-prototype/node_modules/pg/lib/client.js:171:26)
at emitOne (events.js:77:13)
at emit (events.js:169:7)
at Socket.<anonymous> (/home/rof/src/github.com/podtogether/pod-test-prototype/node_modules/pg/lib/connection.js:109:12)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at readableAddChunk (_stream_readable.js:146:16)
at Socket.Readable.push (_stream_readable.js:110:10)
at TCP.onread (net.js:523:20)
1) "before each" hook for "User should have the correct fields"
Locally, these unittests haven't failed (I've run it perhaps... 60 times in a row). I saw similar issues earlier when I didn't use the done callback in the beforeEach and afterEach. Both of those were async and needed to wait before continuing. After fixing that, I stopped seeing these issues locally.
Can anyone shed some light on this issue? (ssh'ed into Codeship and ran the tests resulted in the 1 / ~15 error)

I had this issue with my QA database. Sometimes a new record would save to the database, and sometimes it would fail. When performing the same process on my dev workstation it would succeed every time.
When I caught the error and printed the full results to the console, it confirmed that a unique constraint as being violated - specifically, the primary key id column, which was set to default to an autoincremented value.
I had seeded my database with records, and even though the ids of those records were also set to autoincrement, the ids of the 200-some records were scattered between 1 and 2000, but the database's autoincrement sequence was set to start at 1. Usually the next id in sequence was unused, but occasionally it was already occupied, and the database would return this error.
I used the answer here to reset the sequence to start after the last of my seeded records, and now it works every time.
If you are seeding records to run integration tests on, it is possible that the database autoincrement sequence isn't set to follow them. Sequelize doesn't have this functionality because it's a simple, single command operation that needs to be run in the database.

I had this issue. It was caused by the autoincrement not being set correctly after seeding. The root issue was that our seed methods were explicitly setting the primary/autoincremented key (id) in the seed method, which should generally be avoided. We remove the ids, and the issue was resolved.
Here's a reference to the sequelize issue where we found the solution: https://github.com/sequelize/sequelize/issues/9295#issuecomment-382570944

Related

Is it possible to run Jest in Azure function runtime?

This might be a case of 'you're using the wrong tools for the job' but I'm going to shoot my question anyways, because this is what I have to work with for now.
So, here goes:
I have to make relatively small applications that periodically run as functions in an Azure environment. These applications perform tasks like fetching data from an API and storing that data on a SFTP server. When I create these applications I use a TDD approach with Jest.
I'd like to react to any problems proactively and solve them before the function runs are scheduled. If I run Jest locally I would notice any of these problems but I'd like to automate this proces. Therefor I'd like to know if it's possible to run these tests from an Azure function and have Azure Warnings notify me when one these runs fail.
What have I tried?
Created new function folder "Jest_Function"
Added an always failing test in a separate file.
/main_functions_folder
/jest_function
- index.js
- function.json
- failingTest.test.js
added the following code to index.js:
const { exec } = require('child_process');
function checkTests() {
return new Promise((resolve, reject) => {
exec('npm run test failingTest.test.js', (error) => {
if (error) reject(error);
else resolve();
});
});
}
module.exports = async function (context) {
try {
await checkTests();
} catch (err) {
context.log('tests failed!');
throw err;
}
};
Transforming the function and running it in the terminal results in expected behaviour:
const { exec } = require('child_process');
function checkTests() {
return new Promise((resolve, reject) => {
exec('npm run test failingTest.test.js', (error) => {
if (error) reject(error);
else resolve();
});
});
}
async function myTest() {
try {
await checkTests();
} catch (err) {
console.log('tests failed!');
throw err;
}
}
myTest();
tests failed!
node:child_process:399
ex = new Error('Command failed: ' + cmd + '\n' + stderr);
^
Error: Command failed: npm run test failingTest.test.js
FAIL jest_function/failingTest.test.js
✕ short test (3 ms)
● short test
expect(received).toBe(expected) // Object.is equality
Expected: 1
Received: 0
1 | test('short test', () => {
> 2 | expect(0).toBe(1);
| ^
3 | });
4 |
at Object.<anonymous> (jest_function/failingTest.test.js:2:13)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.227 s, estimated 1 s
Ran all test suites matching /failingTest.test.js/i.
at ChildProcess.exithandler (node:child_process:399:12)
at ChildProcess.emit (node:events:520:28)
at maybeClose (node:internal/child_process:1092:16)
at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5) {
killed: false,
code: 1,
signal: null,
cmd: 'npm run test failingTest.test.js'
}
Azure
I deployed the function in Azure and manualy ran it. This resulted in a failing function as I expected, but for the wrong reason. It displayed the following error message:
Result: Failure Exception: Error: Command failed: npm run test failingTest.test.js sh: 1: jest: Permission denied
I'm not really sure where to go from here, any help or advice will be appreciated!
Not sure if you can use jest directly from within Functions but I know you can run pupeteer headless in Azure Functions:
https://anthonychu.ca/post/azure-functions-headless-chromium-puppeteer-playwright/
and there's also jest-pupeteer package but not sure if there is a specific limitation on jest in Functions if all of the deps are installed as runtime dependencies.
I was able to make this work using npx instead of npm:
const { exec } = require('child_process');
function checkTests() {
return new Promise((resolve, reject) => {
exec('npx jest jest_function/failingTest.test.js', (error) => {
if (error) reject(error);
else resolve();
});
});
}
module.exports = async function (context) {
try {
await checkTests();
} catch (err) {
context.log('tests failed!');
throw err;
}
};
Looking at the logs I'm not really sure what '330' exactly is, but is assume it is installing jest?
2022-04-19T09:54:06Z [Information] Error: Command failed: npx jest
npx: installed 330 in 32.481s
Anyways I'm glad I got this working now :).

Promisify function that does not exit

I am attempting to util.promisify the bonjour npm package. This is the original use case described in the docs:
var bonjour = require('bonjour')()
// advertise an HTTP server on port 3000
bonjour.publish({ name: 'My Web Server', type: 'http', port: 3000 })
// browse for all http services
bonjour.find({ type: 'http' }, function (service) {
console.log('Found an HTTP server:', service)
})
And this will not exit - bonjour.find() stays open looking for http servers.
I want to promisify this and successfully resolve the promise after scanning for servers. Something like:
var bonjour = require('bonjour')
const util = require('util');
// advertise an HTTP server on port 3000
bonjour().publish({ name: 'My Web Server', type: 'http', port: 3000 })
// promisify the 'find' function
const find = util.promisify(bonjour().find.bind(bonjour()));
(async () => {
try {
const content = await find({ type: 'http' });
console.log(content)
} catch (err) {
// It will always error, although, the value of 'err' is the correct content.
console.error('There was an error');
}
})();
As noted in the comments, it will always throw an error, even though the value of err is the desired output.
The promisify'd process expects an exit code 0, which I suspect isn't happening since the process doesn't return. Is this the right assumption? Does anyone have any other insights or solutions to get my promise to not throw an error but return the value that is currently being thrown?
Thanks!
That's because the bonjour callback does not comply with the Node.js callback signature (err, data) => {}. Indeed, bonjour.find's callback has the success value as first parameter. You could wrap it in a proxy function like this:
function findWrapper(options, func) {
function callback(data, err) {
func(err, data);
}
return bonjour().find(options, callback);
}
const find = util.promisify(findWrapper);

Firestore realtime listener error unhandled in node.js

I have made a function that I am exporting using node.js called return_match_uid. I am importing the function in another express routing file and am using async await, with try and catch to handle the error. But somehow, the errors produced by return_match_uid always slip and are unhandled, even though I am using the error handling for the realtime listener recommended by Firestore doc
Here is the function:
exports.return_match_uid = function return_match_uid() {
return new Promise((resolve, reject) => {
const unsub = db.collection('cities').onSnapshot(() => {
throw ("matching algo error");
resolve();
unsub();
}, err => {
console.log(err);
})
})
})
In another express router file, I am calling the function:
const Router = require('express').Router;
const router = new Router();
const {return_match_uid} = require("./match_algo");
router.get('/match', async (req, res) => {
try {
var match_user = await return_match_uid(req.query.data, req.query.rejected);
res.send(match_user);
}
catch (error) {
console.log("Matching algorithm return error: " + error);
}
})
The error I am throwing inside the function: matching algo error do not get caught by either the err => {console.log(err);}) in the function nor the try catch block in the router. It slips and causes my app to crash. It shows the following error:
throw "matching algo error!";
^
matching algo error!
(Use `node --trace-uncaught ...` to show where the exception was thrown)
[nodemon] app crashed - waiting for file changes before starting...
I am throwing an error inside matching algo error because I have some other codes in there, and there is a possibility that it produces an error. If it does, I would like to make sure that it gets handled properly.

Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" when using Mocha for test in nodejs

i want to write a test for test createUser .
i write this code :
const User = require("../src/Entite/User");
describe("Create User", () => {
it(" Save and Create User ", (done) => {
const addUser = new User({
name: "Kianoush",
family: "Dortaj",
});
addUser
.save()
.then(() => {
assert(!addUser.isNew);
done();
});
});
});
when i run the test use was created in database but it show me this error and test fail :
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (F:\Projects\Nodejs\MongooDB\test\create-user_test.js)
at listOnTimeout (internal/timers.js:549:17)
at processTimers (internal/timers.js:492:7)
whats the problem ? how can i solve that ??
Here a few solutions can be checked.
"scripts": {
"test": "mocha --timeout 10000" <= increase this from 1000 to 10000
},
#### OR ###
it("Test Post Request", function(done) {
this.timeout(10000); //add timeout.
});
Test-specific timeouts may also be applied, or the use of this.timeout(0) to disable timeouts all together:
it('should take less than 500ms', function(done){
this.timeout(500);
setTimeout(done, 300);
});
If both do not work. Try this
const delay = require('delay')
describe('Test', function() {
it('should resolve', async function() {
await delay(1000)
})
})
Somehow the presence of the done argument in the async function breaks the test, even if it's not used, and even if done() is called at the end of the test.

NodeJS: How to handle promise rejection properly & best way to create logs

I'm pretty new to coding and to Node.JS but trying to learn... The first big difficulties I found with Node.JS was to think in an Async way when building your code, now I'm facing another monster: Promises.
Up until now, I've tried to build my code to get something to work and not minding at all the error handling (I know that's dumb, but it helps me learn) but now while running my code I get some errors from time to time.
Since "my program" is basically (for now) a bunch of requests (using request-promise) being made through infinite loops. Some manipulation of the info ({objects}) being received and sending it to a mongodb (via mongoose), I mostly know where the errors are coming from:
The servers (being requested) are returning an error (statusCode !== 200).
Too many requests were made (which is obviously a specific statusCode)
And my code runs mostly smoothly, until I get one of these errors. My objective is now to get back into the code to handle properly these errors and create logs once they occur. Another ideal function would be to restart the loop that yielded the error (request) once they occur (maybe after a setTimeout or something).
My questions are:
Could you recommend some great material on promiseRejection handling that I could dig into? For now I'm using .catch((err) => { foo }) for each promise, but I'm not sure what to do with the err once caught.
Is there out there something that helps with logs and promiseRejection handling (an npm package maybe)?
How can I handle a loop restart? Again, I'm not expecting for you to provide a full response with the whole code (if you can that's obviously even better) but to put me in the right direction (best practices, famous npms or articles to achieve this)!
I really hope I'm not out of the topic and following SO's rule! If not let me know and I'll delete the question or edit and adapt.
Thanks in advance for your help!
******* EDIT ********
Simplifying my code:
[]./module/apiRequest.js[]
var rq = require('request-promise');
var fs = require('fs');
function apiRequest(params, req) {
var date = new Date().toISOString();
var logFileName = '../logs/[KRAKEN]'+date+'errorlog.txt';
var options = {
uri: `https://api.kraken.com/0/public/${params}`,
qs: req,
json: true,
resolveWithFullResponse: true
};
return rq(options).then((res) => {
if (res.statusCode === 200 && !res.body.error.length) {
return res; // <=== THIS FOR AN UNKNOWN PARAM, THIS SERVER RETURNS A 200 WITH AN ERROR OBJECT.
} else {
fs.writeFile(logFileName, res, function(err) {
if (err) return console.log(err); // <==== SINCE A 200 WON'T APPEAR AS AN ERROR I'M TRYING TO HANDLE IT THAT WAY.
console.log(`[ERROR][KRAKEN]: log created!`);
});
}
}).catch((err) => { // <==== AS FAR AS I UNDERSTAND THIS IS FOR ANY OTHER ERROR (STATUSCODE 500 FOR INSTANCE / OR AN ERROR RELATED WITH THE CODE)
fs.writeFile(logFileName, err, function(err) {
if (err) return console.log(err);
console.log(`[ERROR][KRAKEN]: log created!`);
});
});
};
module.exports = {
apiRequest
};
[]./module/app.js[]
var apiRequest = require('./apiRequest.js').apiRequest;
function kraken(item) {
return apiRequest('Ticker', {pair: item}).then((res) => {
var result = {};
var timeStamp = Math.floor(new Date());
Object.keys(res.body.result).forEach((k) => {
result= {
mk: 'kraken',
name: k,
a: res.body.result[k].a,
b: res.body.result[k].b,
c: res.body.result[k].c,
v: res.body.result[k].v,
p: res.body.result[k].p,
t: res.body.result[k].t,
l: res.body.result[k].l,
h: res.body.result[k].h,
o: res.body.result[k].o,
n: timeStamp,
}
});
return result; // <=== THIS OCCURS WHEN THERE'S NO ERROR IN THE APIREQUEST.
}).catch((err) => {
console.log(err); // <==== THIS I'M NOT SURE IF IT GETS THE ERROR BACK FROM APIREQUEST. IF I'M NOT MISTAKEN THAT'S NOT THE CASE, IT'S THE ERROR HANDLER FOR THE 'kraken' FUNCTION I'M NOT SURE WHAT KIND OF ERRORS COULD COME OUT OF THIS...
});
};
module.exports = {
kraken,
}
[]./main.js[]
var fs = require('fs');
var mongo = require('mongodb');
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
// KRAKEN REQUIRE:
var kraken = require('./module/app.js').kraken;
var Krakentick = require('./module/model/krakenModel').Krakentick; //<=== THIS IS THE MODEL FOR MONGOOSE.
async function loopKR() {
setTimeout(
async function () {
var item = ['XBTUSD'];
var data = await kraken(item);
data.forEach((object) => {
if (object.name === 'XXBTZUSD') {
var iname = 'btcusd'
} else {
var iname = 'N/A' };
var tick = new Krakentick({
mk: object.mk,
name: object.name,
a: object.a,
b: object.b,
c: object.c,
v: object.v,
p: object.p,
t: object.t,
l: object.l,
h: object.h,
o: object.o,
n: object.n,
iname: iname,
});
tick.save(function(err, tick) {
if (err) return console.log(err); //<==== THIS IS RELATED WITH MONGOOSE NOT A PROMISE IF I'M NOT MISTAKEN... THEN HANDLING WOULD OCCUR IF I HAD A PROBLEM
console.log(`[SUCCESS][KRAKEN]: ${tick.name} added to db!`);
});
});
loopKR();
}
}, 1100);
};
loopKR();
So as you can see, I'm trying to handle mainly the errors coming out of the request. But how do I send them to a log (is my current code correct? Is there a better way?)? And after the error arises and breaks the loop, how do I restart the loop automatically?
With this code, the errors are not being handled properly... For some reasons I get the following message:
TypeError: Cannot read property 'body' of undefined
at apiRequest.then (fast-crypto/module/app.js:34:22)
at tryCatcher (fast-crypto/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (fast-crypto/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (fast-crypto/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (fast-crypto/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (fast-crypto/node_modules/bluebird/js/release/promise.js:693:18)
at Async._drainQueue (fast-crypto/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (fast-crypto/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (fast-crypto/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:781:20)
at tryOnImmediate (timers.js:743:5)
at processImmediate [as _immediateCallback] (timers.js:714:5) (node:12507) UnhandledPromiseRejectionWarning: Unhandled promise
rejection (rejection id: 1): TypeError: Cannot read property 'name' of
undefined (node:12507) [DEP0018] DeprecationWarning: Unhandled promise
rejections are deprecated. In the future, promise rejections that are
not handled will terminate the Node.js process with a non-zero exit
code. { Error: ENOENT: no such file or directory, open
'../logs/[KRAKEN]2017-08-20T10:58:03.302Zerrorlog.txt' errno: -2,
code: 'ENOENT', syscall: 'open', path:
'../logs/[KRAKEN]2017-08-20T10:58:03.302Zerrorlog.txt' }

Categories