nodejs and TAPE integration issues. App initialization call gets blocked - node.js

I am creating unit tests for nodejs app using "tape". When I run tests, the process gets blocked forever. When I dug deeper, I found that if I run "nodejs mainapp.js" the process doesn't end. That's also blocking running of unit tests.
Looks like nodejs process will not end if there are events registered. In my case, creating a mongo or redis connection or use of node modules such as "node-cache" results into this. It's hard to imagine that all such modules can be avoided.
Any suggestion on how to get around the problem. My test case is really simple so there are on issues there.
By the way, I have verified nodejs doesn't get blocked due to http.listen. Someone could argue about using mockups, I am not looking to do that.
test('dummy test', function(t) {
t.equal('hello world', 'hello world', 'Yes hello world = hellow world');
t.end();
});

The main cause of tape processes keeping alive are MongoDB connections not closed. The easiest way to close a connection when all tests ends, is to create a blank test with instructions to close the MongoDB connection.
The following is an example, in this case using Mongoose:
var test = require('tape');
var mongoose = require('mongoose');
test('test', function (t) {
t.pass('Example');
t.end();
});
test('finish', function (t) {
mongoose.disconnect();
t.pass('closing db connection');
t.end();
});
if the problem is indeed a MongoDB connection, a more proper way to deal with it would be using test.onFinish(fn) according to documentation:
The onFinish hook will get invoked when ALL tape tests have finished
right before tape is about to print the test summary.

Related

Test using mongodb-memory-server is failing/timing out

I’m setting up mongodb-memory-server in my backend for test purposes and am experiencing some issues when running tests that I need to debug. My issue is that when I run my test (which will create a mongodb doc somewhere in the service being tested), the test times out.
As I understand it, this is because when the test is executed and a new mongo doc is trying to be created during the test, I console log mongoose.connection.readyState and it says it’s 0, meaning that mongoose is disconnected. This is strange to me because I added console logs to my connectMongoose() function (pictured below) and it says that mongoose is connected.
So my main question is why does it say mongoose is connected at the end of connectMongoose(), but it says it’s disconnected during the execution of the unit test/service function? How can I ensure that MongoDB-memory-server is fully connected prior to test execution?
Below is a screenshot showing how I am doing the mongoose test connection:
Below this is a screenshot of exactly where and how mongodb-memory-server is being used:
Here is a screenshot of my jest.config.js:
And finally the actual test file which has the failing test (what I’m asking about):
beforeAll(connectMongoose)
beforeEach(clearDatabase)
afterAll(disconnectMongoose)
Your three functions here are async functions, but you don't await them - is it possible that the connect Mongoose returns whilst the promise is still awaiting, and the other code continues despite the async function not having completed yet?
Perhaps this would better serve your purpose?
beforeAll(() => {
await connectMongoose
})
Before :
beforeAll(connectMongoose)
beforeEach(clearDatabase)
afterAll(disconnectMongoose)
After:
beforeAll(async() => {await connectMongoose})
beforeEach(async() => {await clearDatabase})
afterAll(async () => { await disconnectMongoose})
The reason is you should wait until the mongoose connection is done completely and remove
set timeout in connectMongoose function not needed there.If you want to use jest timeout you can use it in the beforeEach function.

How to run multiple integration tests using mocha recursively without getting their hooks all combined?

I have made a few integration test using mocha which run fine when run independently but when i try to run them using : mocha test --recursively .
The behaviour I noticed here is that all the after hooks (probably the before too) are getting combined.
I drop my db in the after hook of each test so I check in between tests and I can find data from the previous tests.
It gets cleared up after the last test somehow.
I have already tried importing them into one file but even that won't serve the purpose.
Here are my hooks.
before(async () => {
app.set('port', SERVER_PORT);
server = http.createServer(app);
server.listen(SERVER_PORT, () => console.log(`API running on localhost:${SERVER_PORT}`));
// Initial feeding of the database
await dookie.push('mongodb://localhost:27017/tests', SEEDDATA);
});
after(async () => {
await mongoose.connection.db.dropDatabase();
server.close();
process.exit(0);
});
THANKS
Use jest as it provides the functionality you're looking for inbuilt.
It's hard to tell what is wrong with your tests without having a closer look at the code, so I'm going to drop here a few ideas that come to my mind, with no guarantee that anything will help.
Possibility 1
Use beforeEach and afterEach rather than before and after. This will ensure that your DB cleanup code is executed after each test, rather than after the last test in a describe function block. Details here.
Possibility 2
You are running your tests in multiple threads with mocha-parallel-tests or some other tool. Make sure that the tests where the DB is being accessed are not being parallelized.
Possibility 3
Your db.dropDatabase call returns before the database is actually dropped, while the request is still pending. You'll have to check your connection or database settings.
If nothing helps, try inserting log statements at the start of each unit test and before/after hook, this will help you understand when the code is actually being run and see what is happening in the wrong order.

How to finish/kill Mocha/Istanbul test cycle with Node.js

I've been working on getting an Azure Mobile App with Node.js backend running locally and testable. I finally got everything working well and started writing my tests. Then, I learned about Istanbul/NYC for testing code coverage.
All appears to be working well, and I am able to get the code coverage file generated for all my *.js files, but only after I manually press Ctrl+C.
Is this the normal way for a set of mocha tests to end? It would seem that there would/should be some way to get to the end of a set of tests and auto-kill the Node.js/express server that was created for the test session.
I'm new to the nuts-and-bolts side of Node.js/express/mocha/nyc. Is my expectation wrong? Is there a way to do what I'd like?
I'm not sure where you are lifting your server (server.listen) but stopping your server on a "global" after should be enough.
What I usually do is create a bootstrap.test.js and specify what should happen before and after tests there and run mocha like this:
mocha /test/bootstrap.test.js /test/unit/**/*.test.js /test/integration/**/*.test.js.
You need to make sure that that after is not inside a describe, so it runs after all tests have completed.
So your bootstrap.test.js should look something like this:
/*
imports and stuff
*/
before(function () {
// LIFT YOUR SERVER //
});
after(function () {
server.close();
});
EDIT:
As for the programmatic equivalent of Ctrl-c, that is process.exit(0)

NodeJS/SailsJS app database block

Understand that NodeJS is a single thread process, but if I have to run a long process database process, do I need to start a web worker to do that?
For example, in a sails JS app, I can call database to create record, but if the database call take times to finish, it will block other user from access the database.
Below are a sample code i tried
var test = function(cb) {
for(i=0;i<10000;i++) {
Company.create({companyName:'Walter Jr'+i}).exec(cb);
}
}
test(function(err,result){
});
console.log("return to client");
return res.view('cargo/view',{
model:result
});
On first request, I see the return almost instant. But if I request it again, I will need to wait for all the records being entered before It will return me the view again.
What is the common practice for this kinda of blocking issue?
Node.js has non-blocking, asynchronous IO.
read the article below it will help you to restructure your code
http://hueniverse.com/2011/06/29/the-style-of-non-blocking/
Also start using Promises to help you avoid writing blocking IO.

Adding a default before() function for all the test cases (Mocha)

I'm writing functions for my node.js server using TDD(Mocha). For connecting to the database I'm doing
before(function(done){
db.connect(function(){
done();
});
});
and I'm running the test cases using make test and have configured my makefile to run all the js files in that particular folder using mocha *.js
But for each js file I'll have to make a separate connection to the database, otherwise my test cases fail since they do not share common scope with other test files.
So the question is, Is there anything like beforeAll() that would just simply connect once to the database and then run all the test cases? Any help/suggestion appreciated.
You can setup your db connection as a module that each of the Mocha test modules imports.
var db = require('./db');
A good database interface will queue commands you send to it before it has finished connecting. You can use that to your advantage here.
In your before call, simply do something that amounts to a no op. In SQL that would be something simple like a raw query of SELECT 1. You don't care about the result. The return of the query just signifies that the database is ready.
Since each Mocha module uses the same database module, it'll only connect once.
Use this in each of your test modules:
before(function(done) {
db.no_op(done);
});
Then define db.no_op to be a function that performs the no op and takes a callback function.

Resources