Testing mongodb database with mocha and request - node.js

I've got 2 questions that I am searching for an answer for 3 days so far and can't figure it out.
1. When I should connect to the database when testing?
2. I always get an error when running the test: { "before each" hook for "should list all books on /book GET" } and haven't yet found a solution or the exact cause for it. What am I doing wrong? The only answer I have so far is not to call done() twice in beforeEach() but I ain't doing it...
var chai = require('chai'),
expect = chai.expect,
request = require('request'),
mongoose = require('mongoose'),
Book = require('./../models/book');
// book = require('../model')
mongoose.createConnection('mongodb://localhost/books');
describe('Testing the routes', () => {
beforeEach((done) => {
Book.remove({}, (err) => {
if (err) {
console.log(err);
}
});
var newBook = new Book();
newBook.title = "Lord Of The Rings";
newBook.author = "J. R. R. Tolkien";
newBook.pages = 1234;
newBook.year = 2000;
newBook.save((err) => {
if (err) {
console.log(err);
}
done();
});
});
it('should list all books on /book GET', (done) => {
var url = 'http://localhost:8080/book';
request.get(url, (error, response, body) => {
expect(body).to.be.an('array');
expect(body.length).to.equal(1);
done();
});
});
});

mongoose.createConnection is an asynchronous function. The function returns and Node.js continues on before the connection is actually established.
Mongoose returns promises for most asynchronous functions. Similar to using done, mocha supports waiting for promises to resolve/reject out of the box. As long as the promise is the return value to the mocha function.
describe('Testing the routes', function(){
before('connect', function(){
return mongoose.createConnection('mongodb://localhost/books')
})
beforeEach(function(){
return Book.remove({})
})
beforeEach(function(){
var newBook = new Book();
newBook.title = "Lord Of The Rings";
newBook.author = "J. R. R. Tolkien";
newBook.pages = 1234;
newBook.year = 2000;
return newBook.save();
});
it('should list all books on /book GET', function(done){
var url = 'http://localhost:8080/book';
request.get(url, (error, response, body) => {
if (error) done(error)
expect(body).to.be.an('array');
expect(body.length).to.equal(1);
done();
});
});
});
Also mocha makes use of this for configuration so avoid using arrow functions for the mocha definitions.

Related

Resolution method is overspecified when testing with Mocha and Supertest for Node.js [duplicate]

After the upgrade, Mocha can not even run a simple test here is the code
const assert = require('assert');
it('should complete this test', function (done) {
return new Promise(function (resolve) {
assert.ok(true);
resolve();
})
.then(done);
});
I took this code from here
I understood that it now throws an exception Error: Resolution method is overspecified. Specify a callback * or * return a Promise; not both.
But how to make it work? I did not understand. I have
node -v 6.9.4
mocha -v 3.2.0
How to run this code are now in a new and correct format?
Just drop
.then(done); and replace function(done) with function()
You are returning a Promise so calling done is redundant as it said in error message
In the elder versions you had to use callback in case of async methods like that
it ('returns async', function(done) {
callAsync()
.then(function(result) {
assert.ok(result);
done();
});
})
Now you have an alternative of returning a Promise
it ('returns async', function() {
return new Promise(function (resolve) {
callAsync()
.then(function(result) {
assert.ok(result);
resolve();
});
});
})
But using both is misleading
(see for example here https://github.com/mochajs/mocha/issues/2407)
Mocha allows to either use a callback:
it('should complete this test', function (done) {
new Promise(function (resolve) {
assert.ok(true);
resolve();
})
.then(done);
});
OR return a promise:
it('should complete this test', function () {
return new Promise(function (resolve) {
assert.ok(true);
resolve();
});
});
// Or in the async manner
it('should complete this test', async () => {
await Promise.resolve();
assert.ok(true);
});
You can't do both.
I had to removed the done from the function parameter and the done() of the function call
Before
before(async function (done) {
user = new User({ ...});
await user.save();
done()
});
After
before(async function () {
user = new User({ ...});
await user.save();
});
These works for me
I had this same issue. A lot of times Mocha is paired with another library called Chai. Chai has a package called "chai-as-promised". It gives you the super simple ability to write less code and test promises. In your case of just testing if a promise resolves, it seems perfect.
const chai = require('chai');
const chaiAsPromised = require("chai-as-promised");
const should = require("chai").should();
chai.use(chaiAsPromised);
describe("Testing with correct syntax and non repeated names", () => {
it("Should give us a positive response", () => {
graphQL.sendToGQL(model,"specialEndpoint").should.eventually.be.an("Object");
})
})
An example of async functions with done breaking.
Failure Case
it('If the credentials exists in the system it should return the token generated against it.', async (done) => {
let aObj = await admin.createAdmin();
chai.request(server)
.post("/authenticate")
.set("Content-Type", "application/x-www-form-urlencoded")
.send({username: aObj.login,password:aObj.password})
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a("string");
done();
});
});
Success Case
it('If the credentials exists in the system it should return the token generated against it.', async () => {
let adminObj = await admin.createAdmin();
chai.request(server)
.post("/auth/login")
.set("Content-Type", "application/x-www-form-urlencoded")
.send({username: adminObj.login,password:adminObj.password})
.end((err, res) => {
res.should.have.status(200);
res.body.should.be.a("string");
// done();
});
});
If you don't have callbacks, prior answers (which suggest deleting the done) is correct.
If need to both await some external promise, and then exercise a callback/errback-based implementation in your test, that solution doesn't help you.
You can use a library like pify to convert the callback API to use promises.
Alternatively, you can use a Latch in your callback:
it("test", async () => {
const l = new Latch()
const v = await promiseValue()
s.methodThatTakesCallback((err, result) => {
expect(result).to.eql(expected)
l.resolve() // < notifies mocha your test is done
})
return l.promise
})
In TypeScript, here's a very stripped-down Latch implementation:
/**
* Simple one-count concurrent barrier
*/
export class Latch {
readonly promise: Promise<void>
resolve!: () => void
constructor() {
this.promise = new Promise<void>(resolve => (this.resolve = resolve))
}
}
Just emit done callback completely and use async instead.
(This implementation is based on an express api running on firebase functions, using a custom jsonwebtoken)
const { FIREBASE_UID } = require('dotenv').config()?.parsed
const chai = require('chai');
const chaiHttp = require('chai-http');
const server = require('../lib/api').API;
const should = chai.should();
const expect = chai.expect
chai.use(chaiHttp)
const test = chai.request(server).keepOpen()
// get your token with an earlier mock request and store to a var
describe('Just checking a token', () => {
let some_token
it('should print custom jwt for testing, status: 200'), async () => {
try {
const res = await test.get(`/createCustomFirebaseToken/${FIREBASE_UID}`).send()
res.should.exist
res.should.have.status(200);
res.should.have.json
some_token = (JSON.parse(res.text)).token
} catch (error) {
throw error
}
}
it('should print details:PING, status:200'), async () => {
try {
const res = await test.get('/').set('Authorization',`Bearer ${some_token}`)
.send()
res.should.exist
res.should.have.status(200);
res.should.have.json
const { details, status } = JSON.parse(res.text)
expect(details).to.equal('PING')
expect(status).to.equal(200)
} catch (error) {
throw error
}
}
after(() => test.close())
})

node.js How to get express.post to wait for the net.client.data event

How to have express.post to wait for a response from a socket created using net client? net here means the package require("net")
Architecture
browser <-> express with built in unix domain client <-> some unix domain server
My express server serves the front end as usual. Sometimes, it gets information from other services running on the same machine. These services are outside my control. I use net to create a client to connect with them and this works fine.
Tried approaches
All the usual answers about express.post using, for example, a promise, are not applicable because they wait for a reply on the function you call.
For example. fs.readFile will return something related to the completion of fs.readFile and this can easily be promisified using the examples on the internet.
Node.js promise request return
https://www.intuz.com/blog/promises-in-node-js-with-examples
https://dzone.com/articles/how-to-interact-with-a-database-using-promises-in
https://www.turtle-techies.com/using-promises-with-express-js/
The problem
However, with net, the reply comes from somewhere else.
client.write is the method for sending. This method just returns true, not the response from the server.
We become aware of the response at the client.data event and I can't figure how to get a promise to watch the client.data event to fulfill the promise.
My best attempt
Using turtle-techies as an example (all above are similar though differing syntax):
const readFilePromise = (filename) => new Promise((resolve, reject) => {
fs.readFile(filename, 'utf-8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
const app = express();
//call the promisified long-running function. ONLY works if the function returns the data you need. client.write does not.
app.post('/get-file', (req, res) => {
readFilePromise('important_file.txt')
.then(data => res.end(data))
.catch(err => res.end(`could not serve data: ${err}`))
});
Now I try rewriting the promisified function or method to suit net.client:
var net = require('net');
var socketName = '/tmp/dp.sock';
var client = net.createConnection(socketName);
client.on("connect", function() {
client.write('client on connect');
});
client.on("data", function(data) {
console.log("client.on data: ", data.toString());
//I don't see a way to get a handle here on express.post req,res so
// I think the answer lies elswhere. Anyway, it would be messy to put it here.
});
client.on('close', function() {
console.log('client on close');
});
//========= end of client building ===========
//========= promisified client.write =========
const readFilePromise = (filename) => new Promise((resolve, reject) => {
client.write('my message'); //This just returns true which I don't care about
//now what to do here to become aware of client.ondata and handle its data?
});
I have a feeling the answer is in front of my face.
The answer is here: https://techbrij.com/node-js-tcp-server-client-promisify
In principle, wrap the client creation and client.write in a new class in which you can then do any promisification you like.
In case the link breaks, here's what they say (modified by me to be for unix domain socket; techbrij.com did tcp)
//in a module.js file
const net = require('net');
const DEF_socketName = '/tmp/echo.sock';
class Client {
constructor(socketName = '/tmp/echo.sock') {
this.socket = new net.createConnection(socketName);
this.address = socketName || DEF_socketName;
this.init();
}
init() {
var client = this;
client.socket.on("connect", function() {
client.socket.write('hello from unix client!');
});
client.socket.on("data", function(data) { //approahch 1 here we delete the function def and simply put dodata
console.log("client.on data: ", data.toString());
//client.destroy();
});
client.socket.on('close', function() {
console.log('Connection closed');
});
}
sendMessage(message) {
console.log('client.sendMessage: ' + message);
var client = this;
return new Promise((resolve, reject) => {
client.socket.write(message);
client.socket.on('data', (data) => {
resolve(data);
if (data.toString().endsWith('exit')) {
client.socket.destroy();
}
});
client.socket.on('error', (err) => {
reject(err);
});
});
}
}
module.exports = Client;
Then in a client.js file:
const Client = require('./client_mod');
const client = new Client();
client.sendMessage('A')
.then((data)=> { console.log(`Received: ${data}`); return client.sendMessage('B');} )
.then((data)=> { console.log(`Received: ${data}`); return client.sendMessage('C');} )
.then((data)=> { console.log(`Received: ${data}`); return client.sendMessage('exit');} )
.catch((err) =>{ console.error(err); })

Ensuring Document is Retrieved Without Using setTimeout() in Mocha Test

I have written some tests in my Node project using Mocha and Chai. In one of my tests I create an agenda.js job, and then save it to the database. Then I retrieve that document from my MongoDB database and run some checks on it. After numerous configurations, I've found a construction for the test that works. But to get this to work I had to add a setTimeout() within the first it block, because otherwise the it checks start running before the document is retrieved from the database.
While the following construction works, I'd like to know what would be a better way of doing this. It seems to me the whole point of the before block in Mocha is to ensure that whatever work is defined within it is done BEFORE the it checks run. That doesn't seem to be happening in my case - hence the need for the setTimeout(). So how can I accomplish that without resorting to using the `setTimeout()?:
const assert = require("chai").assert;
const expect = require("chai").expect;
const chai = require("chai");
chai.use(require("chai-datetime"));
const Agenda = require('agenda');
const config = require('./../../configuration');
const url = config.get('MONGO_URL');
const dbName = config.get('MONGO_DATABASE');
const collection = config.get('MONGO_COLLECTION');
const createAgendaJob = require('./../../lib/agenda-jobs/contact-firstname-to-proper-case');
const MongoClient = require('mongodb').MongoClient;
const client = new MongoClient(url);
describe("Contact FirstName to Proper Case", async function () {
const jobName = "Contact FirstName To Proper Case";
const testDate = new Date(2019, 01, 01);
let result;
let agenda;
this.timeout(10000);
before(async function () {
const connectionOpts = {
db: {
address: `${url}/${dbName}`,
collection
}
};
agenda = new Agenda(connectionOpts);
await new Promise(resolve => agenda.once('ready', resolve));
await createAgendaJob(agenda);
});
describe("Check Contact FirstName To ProperCase Found Job", async function () {
let result;
before(async function () {
await client.connect(async function (err) {
assert.equal(null, err);
const db = await client.db(dbName);
result = await db.collection("jobs").findOne({
"name": jobName
});
client.close();
});
});
it("should have a property 'name'", async function () {
await new Promise(resolve => setTimeout(resolve, 1000)); // Here is the setTimout()
expect(result).to.have.property("name");
});
it("should have a 'name' of 'Contact FirstName To Proper Case'", async function () {
expect(result.name).to.equal("Contact FirstName To Proper Case");
});
it("should have a property 'type'", function () {
expect(result).to.have.property("type");
});
it("should have a 'type' of 'normal'", function () {
expect(result.type).to.equal("normal");
});
it("should have a property 'repeatTimezone'", function () {
expect(result).to.have.property("repeatTimezone");
});
it("should have a property 'repeatInterval'", function () {
expect(result).to.have.property("repeatInterval");
});
it("should have a property 'lastModifiedBy'", function () {
expect(result).to.have.property("lastModifiedBy");
});
it("should have a property 'nextRunAt'", function () {
expect(result).to.have.property("nextRunAt");
});
it("should return a date for the 'nextRunAt' property", function () {
assert.typeOf(result.nextRunAt, "date");
});
it("should 'nextRunAt' to be a date after test date", function () {
expect(result.nextRunAt).to.afterDate(testDate);
});
});
});
The async function inside before may be resolving early. In that case I would wrap it in a new Promise and resolve when I am sure all async code has resolved to completion.
//...
before(function () {
return new Promise((resolve, reject) => {
client.connect(async function (err) {
if(err) return reject(err);
try {
const db = await client.db(dbName);
result = await db.collection("jobs").findOne({
"name": jobName
});
client.close();
} catch(err){
return reject(err);
}
return resolve();
});
});
})
//...
Alternatively, call the done callback, passing in a truthy value if there is an error.
//...
before(function (done) {
client.connect(async function (err) {
if(err) return done(err);
try {
const db = await client.db(dbName);
result = await db.collection("jobs").findOne({
"name": jobName
});
client.close();
} catch(err){
return done(err);
}
done();
});
})
//...

doing a mocha Test for ARI file?

I wish doing a test for ARI ! but i cant have a request for connection with asterisk . whene i run my file with node its ok , but if i run it with mocha no result !
let chai = require('chai');
let request = require('request');
let uuid = require('uuid');
let should = chai.should();
let ari = require('ari-client');
let expect = chai.expect;
let sinon = require('sinon');
describe('Tests originationDevice ', function () {
it(" should make a call ", function (done) {
ari.connect("http://192.168.0.62:8088", "username", "password")
.then(function (ari) {
console.log('its okey');
})
.catch(function (err) {
console.log('errrror');
});
done();
});
});
Well, its just one of solution but strongly recommend to mock external api calls-
try-
it(" should make a call ", function (done) {
ari.connect("http://192.168.0.62:8088", "username", "password")
.then(function (ari) {
console.log('its okey');
res.should.true; // something like that.
done(); // calling done function
})
.catch(function (err) {
console.log('errrror');
// assert something
done(); // call done function
});
});

node-redis promisification using bluebird

I'm trying to use promises with node-redis package, but I can't use on.connect() method.
var redis = require("redis");
var client = redis.createClient();
bluebird.promisifyAll(redis.RedisClient.prototype);
bluebird.promisifyAll(redis.Multi.prototype);
// callback version
app.get('/redis', function(req, res) {
client.set("foo_rand000000000000", "some fantastic value", function(err, reply) {
if (err) {
console.log(err);
} else {
console.log(reply);
}
res.end();
});
});
// promisified version
app.get('/redis', function(req, res) {
return client.setAsync("foo_rand000000000000", "some fantastic value").then(function(return) {
console.log(return); // returns OK
client.quit();
});
});
But I am stuck with the one below, how can I promisify it?
// example
client.on("connect", function () {
client.set("foo_rand000000000000", "some fantastic value", redis.print);
client.get("foo_rand000000000000", redis.print);
});
I tried the one below but it doesn't work, I can't see the response on the command line:
app.get('/redis', function(req, res) {
return client.onAsync("connect").then(function(res) {
console.log(res);
res.end();
});
});
like Freyday siad, on is not async method, but an event emitter, so I would strongly discourage you from promisfying it, but hey, if you are insistant you could do something like:
let _connectResolve, _connectReject, onConnected = new Promise((resolve, reject) => {
_connectResolve = resolve;
_connectReject = reject;
}), redis = require("redis"),
client = redis.createClient();
client.on('connect', _connectResolve);
// usage example:
onConnected.then(() => {
client.setAsync("foo_rand000000000000", "some fantastic value").then(redis.print);
client.getAsync("foo_rand000000000000").then(redis.print);
});
if your worry is, you have to wait for client to connect before you get/ set stuff, you can chain all your calls to onConnected promise. e.g:
app.get('/redis', (req, res) => {
onConnected
.then(() => client.setAsync("foo_rand000000000000", "some fantastic value"))
.then(() => res.end());
});
The client.on() method is coming from the EventEmitter prototype which the redis client likely inherits from. You could try to walk the prototype chain and promisify it as well, but I'd probably just handle it myself like this:
function onConnect(client) {
return new Promise(function(resolve, reject) {
client.on('connect', function(err) {
if (err) return reject(err)
return resolve()
})
})
}
Then you'll be able to use it like this:
app.get('/redis', function(req, res) {
return onConnect(client)
.then(function() {
return client.setAsync("foo_rand000000000000", "some fantastic value")
})
.then(function(result) {
console.log(result); // returns OK
client.quit();
res.end();
});
});
});

Resources