Running Mocha multiple times with the same data produces different results - node.js

I have been noticing. With no discernible pattern, that sometimes I run my mocha tests and get a failed assertion. then I run it again immediately. Without making any changes and the assertions all pass. Is there something that I'm doing wrong. Is there test data that is cached?
I, unfortunately don't know what to post, since I can't seem to pin this down to any one thing but here is one function I've seen it happen to
mysqltest.js
describe('get_tablet_station_name', function() {
it ('isSuccessful', function() {
mysqlDao.init();
var callback = sinon.spy();
mysqlDao.get_tablet_station_name(state.TABLET_NAME, function(err, result) {
assert(err == undefined)
});
});
it ('isUnsuccessful', function() {
mysqlDao.init();
var callback = sinon.spy();
mysqlDao.get_tablet_station_name("'''%\0", function(err, result) {
assert(err != undefined);
});
});
});
When the assertions fail it is
assert(err != undefined);
err is returning null despite the bad SQL statement.

You should share the error you are getting when test case is getting failed.
But from you code and problem described, I can guess that your mysql calls must be taking time greater than the default timeout of mocha test cases. And while running your test case for the second time mysql must be returning data from cache hence preventing timeout.
To debug try increasing the default timeout of your test case, and for that use inside you describe call ->
describe('get_tablet_station_name', function() {
this.timeout(10000);
......//rest of the code
Please note this could not be the solution,please provide why assertion is getting failed if above mentioned thing do not work.

Related

Jest test won't pass, even if the first test is commented

I was writing tests for some authentication endpoints when I came across a bug like issue that I cannot seem to figure out.
This test won't pass:
it("Testing /auth/signup/lol", () => {
const test = true;
expect(test).toBe(true);
console.log("finished test?");
});
The only way I can reproduce this issue is taking all the setup and teardown code, then moving it to another file, along with the test that's troubling me (as I have done, this test copied from auth.test.js).
I've spent the morning trying to figure out the issue, the only time the test has passed is when I removed the setup code. However on notebooks.test.js and auth.test.js (excluding the last two three tests at the bottom of the auth.tests.js script) the setup codes works as intended.
What's wrong with this code?
Steps to reproduce:
Clone this repository
Switch to the develop branch
Go to the backend directory
Install all packages
Run 'npm test tests/endpoints/auth2.test.js'
I would post a small program reproducing the issue, but all attempts to do so failed.
there's a timeout in the afterEach() method because collections.users.drop() returns an undefined value (result is undefined).
At the minimum, add an else clause when testing result value so you can exit method before reaching the 10s timeout.
Maybe some additional code is required but I don't know the logic of your code and test so maybe afterEach should do more things.
Here is the working code:
afterEach(done => {
server.getTokenManager().empty()
let collections = server.getClient()?.connection.collections
if (collections === undefined) {
done()
return
}
if (collections.users !== undefined) {
collections.users.drop((err: any, result: any) => {
if (result) {
done()
} else {
done()
}
})
}
}, 10000)
The rest of the code is ok.

Using a domain to test for an error thrown deep in the call stack in node.

I'm trying to write some tests that catch errors that are potentially thrown deep in a nest of callbacks and I decided to try using domains for this. I've managed to simplify to the following test case:
"use strict";
var assert = require("assert");
var domain = require("domain");
function wrapInDomain(throwsAnError, callback) {
var thisDomain = domain.create();
thisDomain.on("error", function(error) {
console.log("calling callback");
//thisDomain.destory(); // I'm not sure if I should do this
callback(error);
});
thisDomain.run(function() {
process.nextTick(function(){
throwsAnError();
});
});
}
function throwsAnError() {
process.nextTick(function(){
throw new Error("I sensed a great disturbance in the force, as if millions of voices cried out in terror and were suddenly silenced. I fear something terrible has happened.");
});
}
describe("describe something that throws an error", function(){
it("it clause", function(done) {
wrapInDomain(throwsAnError, function(theError) {
console.log("got an error " + theError);
assert(false); //Assert something
done();
});
});
});
If the assert passes mocha gives the nice colourful summary of how many tests passed or failed. But if an assert fails, node seems to crash and drops directly. The error listed is the original rather than the failed assert.
Am I doing something very wrong here? Or is this some kind of bug that needs reporting?
calling callback
got an error Error: I sensed a great disturbance in the force, as if millions of voices cried out in terror and were suddenly silenced. I fear something terrible has happened.
/home/gareth2/cloud/apifacade/src/test/resources/testCase.js:23
throw new Error("I sensed a great disturbance in the force, as if mill
^
Error: I sensed a great disturbance in the force, as if millions of voices cried out in terror and were suddenly silenced. I fear something terrible has happened.
at /home/gareth2/cloud/apifacade/src/test/resources/testCase.js:23:15
at process._tickDomainCallback (node.js:463:13)
*node crashes*
I'm using the following version of node.
$ node --version
v0.10.33
The problem is that you need to exit the domain before Mocha can trap the failing exception, because event handlers that are bound to a domain execute in the domain. If you change your error handler to this, it will work:
thisDomain.on("error", function(error) {
thisDomain.exit();
process.nextTick(function () {
callback(error);
console.log("calling callback");
});
});
You need to call process.nextTick (or setImmediate or setTimeout(..., 0)) in the code above so that the statement callback(error) executes in the domain that becomes effective after thisDomain.exit() runs. The way Node works, when you create a new callback for handling an event or to run with process.nextTick (or equivalent functions), then the callback as a whole is associated with a specific domain. Suppose the following callback
myDomain.on("error", function () {
A;
myDomain.exit();
B;
});
Any error caused by A will be handled in myDomain, but the same is true of B because B belongs to the same callback as A.
By using process.nextTick, we create a new callback which is associated with the new domain that takes effect after thisDomain.exit() executes. Modifying the example above, it would be:
myDomain.on("error", function () {
A;
myDomain.exit();
process.nextTick(function () {
B;
});
});
Now B belongs to a different callback from A and this callback was created after we exited myDomain so it executes in the domain that was in effect before myDomain was created.

NodeUnit testing mysql function test always successful

I'm trying to learn how to use NodeUnit to test my NodeJs code. Ive written the following code, however each time I run the test, the result is OK: 0 assertions, no matter whether the input parameter is valid or not. Can anyone explain why this doesn't work and how I can fix it?
auth.class.js: This function accepts a user ID and returns a username.
exports.username = function(uid, callback) {
db.query('SELECT username FROM ul_logins WHERE id=?', uid, function(err, results){
if (err) throw new Error(err);
if(results.length > 0)
{
callback(null, results[0].username);
}
else
throw new Error("No results.");
});
};
authtest.js: This test will run successful every time, no matter what the uid is, and count 0 assertions.
var auth = require('./auth.class.js');
exports['username'] = function (test) {
auth.username(1, function(err, data){
return test.equal(data, "joe#example.com");
});
test.done();
};
The function you are testing is asynchronous (see the rewritten function below). You need to put the test.done() in the callback function:
exports['username'] = function (test) {
test.expect(2);
auth.username(1, function (err, data) {
test.ifError(err);
test.equal(data, 'joe#example.com');
test.done();
});
};
In your version, test.done gets called before the callback to auth.username is called. Use test.expect to tell nodeunit how many asserts it should receive before test.done is called.
You have a serious problem in your auth.username function. You should not throw in asynchronous code since a try-catch cannot be used to catch the error, leading to uncaught exceptions. You should always pass errors in asynchronous code to a callback as the first argument (convention). Your function should look like:
exports.username = function (uid, callback) {
var query = 'SELECT username FROM ul_logins WHERE id=?';
db.query(query, uid, function (err, results) {
if (err) {
return callback(err);
}
if (results.length === 0) {
return callback(new Error('No user found.'));
}
callback(null, results[0].username);
});
};
Note that errors are handled first (keeps the code neat), and callback calls in the branches are returned to avoid calling the callback multiple times (using else adds a level of indentation).
I get the impression that you are new to Node, and I remember having difficulty over this point too. Consider any function that does something over the network as asynchronous. This could take a long time, so to avoid blocking the process Node gets the OS to handle the task, and takes a callback to call at some point in the future when the OS gives it a result. This is why Node relies so heavily on callbacks. It leaves the Node process free to do other things (like call test.done in your question) while it waits. It also means that try-catch (which can only catch errors thrown in the same 'tick') no longer works. The conventional way to handle errors is to call the callback with the error as the first argument. All other arguments are for actual results.

Assertion in event brake down Mocha when run programmatically

I have problem with Mocha.
If i run this programmaticaly from Jake Mocha brakes down and don't show nothing more than some errors stuff like:
AssertionError: There is a code 200 in response
at Socket.<anonymous> (/home/X/Y/Z/test/test_Server.js:70:4)
at Socket.EventEmitter.emit (events.js:93:17)
at TCP.onread (net.js:418:51)
Runned from command line gives more expected results. That is:
19 passing (30ms)
7 failing
1) RTDB accepts connection with package and response with code 200 if correct package was send:
Uncaught AssertionError: There is a code 200 in response
at Socket.<anonymous> (/X/Y/Z/test/test_Server.js:70:4)
at Socket.EventEmitter.emit (events.js:93:17)
at TCP.onread (net.js:418:51)
2) XYZ should be able to store GHJ for IJS:
Error: expected f...
...
The problem is following code:
test('accepts connection with package and response with code 400 ' +
'if wrong package was send', function (done) {
console.log('client connecting to server');
var message = '';
var client = net.connect(8122, 'localhost', function () {
client.write('Hello');
client.end();
} );
client.setEncoding('utf8');
client.on('data', function (data) {
message += data;
} );
client.on('end', function (data) {
assert(message.indexOf('400') !== -1, 'There is a code 400 in response');
done();
});
client.on('error', function(e) {
throw new Error('Client error: ' + e);
});
});
If I do
assert(message.indexOf('400') !== -1, 'There is a code 400 in response');
just after
var message = '';
Mocha fails correctly (I mean displaying errors etc.), So this is fault of asynch assertion done on event. How can I correct that? Thats real problem Because this test is first, and I get no clue where to look for source of problem (If there is any). Should I somehow catch this assertion error and pass it to Mocha?
EDIT:
Answer to comment how is Jake running Mocha - just like that:
var Mocha = require('mocha');
...
task("test", [], function() {
// First, you need to instantiate a Mocha instance.
var mocha = new Mocha({
ui: 'tdd',
reporter: 'dot'
});
// Then, you need to use the method "addFile" on the mocha
// object for each file.
var dir = 'test';
fs.readdirSync(dir).filter(function(file){
// Only keep the .js files
return file.substr(-3) === '.js';
}).forEach(function(file){
// Use the method "addFile" to add the file to mocha
mocha.addFile(
path.join(dir, file)
);
});
// Now, you can run the tests.
mocha.run(function(failures){
if(failures){
fail("Mocha test failed");
} else {
complete();
}
});
}, {async: true});
I'm assuming since you say "programmatically" that your Jakefile issues require("mocha") and then creates a Mocha object on which it calls the run method.
If this is the case, then the reason it does not work is because Jake and Mocha are working at cross purposes. When Mocha executes a test, it traps unhandled exceptions. Schematically, (omitting details that are not important) it is something like:
try {
test.run();
}
catch (ex) {
recordFailure();
}
It is at the call to test.run that the test is executed. For tests that are purely synchronous, no problem. When a test is asynchronous, the asynchronous callback which is part of the test cannot execute inside the try... catch block Mocha establishes. The test will launch the asynchronous operation and return immediately. At some point in the future, the asynchronous operation calls the callback. When this happens, Mocha is not able to catch the exception in the asynchronous operation with a try... catch block. How does it catch such exceptions then? It listens to uncaughtException events.
Now, the problem when Mocha is run in the same execution context as Jake is that Jake also wants to trap uncaught exceptions. Jake sometimes has to launch asynchronous operations and wants to trap cases where these operations fail, so it listens to uncaughtException too. It installs its listener first. So when an asynchronous Mocha test fails with a exception, Jake's listener's is called, which cause Jake to immediately stop execution. Mocha never gets a chance to act.
I don't see a clear way to make both Jake and Mocha cooperate when run in the same execution context. There might be a way to fiddle with the handlers but I doubt that there is a robust way to make it work. (By "robust" I mean a way which will ensure that every single error is trapped and attributed to the correct source.) The vm module might help segregate their contexts while keeping them in the same OS process.
Based on this answer: https://stackoverflow.com/a/9132271/2024650
In few words: I remove listener on uncaughtException in Jake. This allow Mocha to handle this uncaughtExceptions. At the end I add back this listener.
This solves my answer for now:
task("test", [], function() {
var originalExeption = process.listeners('uncaughtException').pop();
//!!!in node 0.10.X you should also check if process.removeListener isn't necessary!!!
console.log(originalExeption);
// First, you need to instantiate a Mocha instance.
var mocha = new Mocha({
ui: 'tdd',
reporter: 'dot'
});
// Then, you need to use the method "addFile" on the mocha
// object for each file.
var dir = 'test';
fs.readdirSync(dir).filter(function(file){
// Only keep the .js files
return file.substr(-3) === '.js';
}).forEach(function(file){
// Use the method "addFile" to add the file to mocha
mocha.addFile(
path.join(dir, file)
);
});
// Now, you can run the tests.
mocha.run(function(failures){
if(failures){
fail("Mocha test failed");
} else {
complete();
}
process.listeners('uncaughtException').push(originalExeption);
});
}, {async: true});
it seems that you are testing a HTTP server by connecting with TCP to it, (correct if i'm wrong) if thats the case here, you should just drop your current test, and use appropriate module to test an HTTP server or REST API there are plenty modules like Superagent .
You should try call client.end() after you have received your first data event, this way it will call assert after first header is received.
if you want to continuously send and test requests, have all you assert in the data event and call correct assert each time it receives the header you want to test, just remember that you must call done() when its supposed to finish, and that it can't be delayed for a long period of time, the request must be one after another.
Other than that you can use async module if you want to test chained requests ( one request depends on another and another and so on..), in some case its useful to raise the mocha timeout to more than 10000 (10secs) to give the async part some time to complete.

wait for async to complete before return

mongoosejs async code .
userSchema.static('alreadyExists',function(name){
var isPresent;
this.count({alias : name },function(err,count){
isPresent = !!count
});
console.log('Value of flag '+isPresent);
return isPresent;
});
I know isPresent is returned before the this.count async function calls the callback , so its value is undefined . But how do i wait for callback to change value of isPresent and then safely return ?
what effect does
(function(){ asynccalls() asynccall() })(); has in the async flow .
What happens if var foo = asynccall() or (function(){})()
Will the above two make return wait ?
can process.nextTick() help?
I know there are lot of questions like these , but nothing explained about problem of returning before async completion
There is no way to do that. You need to change the signature of your function to take a callback rather than returning a value.
Making IO async is one of the main motivation of Node.js, and waiting for an async call to be completed defeats the purpose.
If you give me more context on what you are trying to achieve, I can give you pointers on how to implement it with callbacks.
Edit: You need something like the following:
userSchema.static('alreadyExists',function (name, callback) {
this.count({alias : name}, function (err, count) {
callback(err, err ? null : !!count);
console.log('Value of flag ' + !!count);
});
});
Then, you can use it like:
User.alreadyExists('username', function (err, exists) {
if (err) {
// Handle error
return;
}
if (exists) {
// Pick another username.
} else {
// Continue with this username.
}
}
Had the same problem. I wanted my mocha tests to run very fast (as they originally did), but at the same time to have a anti-DOS layer present and operational in my app. Running those tests just as they originally worked was crazy fast and ddos module I'm using started to response with Too Many Requests error, making the tests fail. I didn't want to disable it just for test purposes (I actually wanted to have automated tests to verify Too Many Requests cases to be there as well).
I had one place used by all the tests that prepared client for HTTPS requests (filled with proper headers, authenticated, with cookies, etc.). It looked like this more or less:
var agent = thiz.getAgent();
thiz.log('preReq for user ' + thiz.username);
thiz.log('preReq for ' + req.url + ' for agent ' + agent.mochaname);
if(thiz.headers) {
Object.keys(thiz.headers).map(function(header) {
thiz.log('preReq header ' + header);
req.set(header, thiz.headers[header]);
});
}
agent.attachCookies(req);
So I wanted to inject there a sleep that would kick in every 5 times this client was requested by a test to perform a request - so the entire suite would run quickly and every 5-th request would wait to make ddos module consider my request unpunishable by Too Many Requests error.
I searched most of the entries here about Async and other libs or practices. All of them required going for callback - which meant I would have to re-write a couple of hundreds of test cases.
Finally I gave up with any elegant solution and fell to the one that worked for me. Which was adding a for loop trying to check status of non-existing file. It caused a operation to be performed long enough I could calibrate it to last for around 6500 ms.
for(var i = 0; i < 200000; ++i) {
try {
fs.statSync('/path' + i);
} catch(err) {
}
};

Resources