Mocha/Chai: How to perform async test of something that didn't happen? - node.js

I am trying to write a short mocha/chai Node test for some async process, expecting it to ignore irrelevant input. It basically looks like this (compared to the test of relevant input). The problem is how do I write the second test? It's an async process that eventually does nothing, no error/success emits...
it('should process input', function(done) {
object
.on('success', function(result) {
expect.result.to.equal("OK");
done();
})
.asyncDoSomething('relevant input');
});
it('should ignore input', function(done) {
object.asyncDoSomething('irrelevant input');
// TODO: how do I verify the async process eventually did nothing?
});

That's a good one - the only solution that comes to mind is to wait for a timeout and assume if it didn't happen in this time, then it will not happen. But this is not good design and needlessly slows down the test suite.
Have you thought about isolating the decision logic to somewhere where it could be tested synchronously and then make a test for that?

For the moment (still awaiting possibly better solutions?), I have updated the emitter to emit some sort of an 'ignored' event for all cases where it decides to ignore the input asynchronously. For testing, I check the "cause" of the ignore using:
expect(cause).to.equal(expectedCause)

Related

Does firebase functions garantee order of execution for async functions?

I have a firebase function that does lot of checks in the firebase realtime database and then returns a response.
Does the node runtime in firebase garantee that the async functions will be executed in the order they are call? or there is some sort of non fifo scheduler that executes then?
the logic of the real function is a bit complex (over 200 lines) so to avoid the extra complexity i will just use a pseudo function as example:
function checks(req,res){
let resp;
database.ref('nodeA').once('value').then(function(data) {
//do some checks and modify resp
});
database.ref('nodeB').once('value').then(function(data) {
//do some checks and modify resp
});
database.ref('nodeC').once('value').then(function(data) {
//do some checks and modify resp
res.status(200).send(resp);
});
FIRST OF ALL. I know I can make nested calls to the realtime database and garantee the execution of all checks, but my real case scenario is more complex than this and would't work for me
Is there any garantee that all checks will be executed by this sample code?
if not... how can i make a non blocking while that waits it to be ready?
like:
while(!resp.ready){
wait //how to wait without blocking the other functions
}
res.status(200).send(resp);
In the code you shared the order in which the three requests are sent to the database is in the order you specify them. The results are also guaranteed to come in that same order.
So by the time nodeC is loaded, it is guaranteed that the first two callbacks have also been invoked.
try async and await for this case,
in your code, you will send the response to the user before finishing all the validation, there is no guarantee the callback function for each promise will execute in the same order.
async function checks(req,res){
let resp;
let nodeAData=await database.ref('nodeA').once('value');
//do some checks and modify resp
let nodebData=database.ref('nodeB').once('value')
//do some checks and modify resp
.
.
.
res.status(200).send(resp);
});

Can I make Chai's expect.to.not.throw synchronous?

I have a snippet of code that I'm testing in Chai and Pact. It looks something like this:
var myVerify = () => {
provider.verify().then(() => {
console.log('B verified')
done()
})
}
expect(myVerify).to.not.throw()
This works but it's a lot of extra work to go through to make a wrapper function to ensure that I wait on Pact's verify complete's before continuing on with the test. Pact has some internal state that will clear when it's done. If I just call this:
expect(provider.verify()).to.not.throw()
then it will conflict with other tests.
This code seems to work fine for me but it's very messy. Is there a simpler way to accomplish this?
I wouldn't recommend this method since if an error did in fact occur, it would never be caught anyways because promises don't "throw errors", they simply reject the promise, which you can catch using .catch or being the second parameter of the .then.
There are 2 ways of doing what you want:
Just with Mocha:
return provider.verify().then(() => {
console.log('B verified');
done();
}, () => throw new Error("B verification failed"));
In this simple example, we're not using chai to verify anything since you're not actually verifying data output of the verify, you're just checking to see if the promise was a success, if not, throw an error which will fail your tests. Mocha, by default, understands promises as long as they're returned as part of the test.
However, this method means that the wrapping it function needs to inject the done parameter, which I'm not a fan of. What I am a fan of is using:
Chai with Chai as Promised:
You need to set up Chai as Promised using
chai.use(require("chai-as-promised))
then in your tests, simply do:
return expect(provider.verify()).to.eventually.be.fulfilled;
This test will wait for the promise to return, and chai will validate that it is, in fact, fulfilled and not rejected. I find this syntax to be much simpler to use and makes writing tests simpler. You can also have multiple expects with the same promise, using Promises.all:
var verify = provider.verify();
return Promises.all(
expect(verify).to.eventually.be.fulfilled,
expect(verify).to.eventually.be.true,
);

How do I test child processes using chai and mocha?

I'm creating a framework to execute processes at a specific time (cron-like) and to test it I'm using chai-mocha-grunt.
The architecture of solution is based on this example. Basically, we have:
A Master process, which calls the Child (via child_process.fork) a specific number of times.
A Child process, which executes something using setInverval();
A process to call the Master.start() function.
With this architecture how do I test to ensure that threads are executed at the correct time using mocha and chai (with the 'assert' library)?
In other words, how do I make chai 'listen' to the threads and check if they are executed at the correct time?
I'm not sure you need chai itself to listen to your threads. If you're building off of the example you linked this should be pretty straight forward because the Master.js is already an EventEmitter and it's already emitting all events it hears from the child processes.
Your test structure could be as simple as this:
describe('ForkExample test', function() {
// Set an appropriate test timeout here
this.timeout(1000);
it('should do stuff at the right time', function(done) {
var fe = new ForkExample();
fe.start(1);
fe.on('event', function(type, pid, e) {
if (type === 'child message') {
// Check here that the timing was within some expected range
done();
}
});
});
});

To async, or not to async in node.js?

I'm still learning the node.js ropes and am just trying to get my head around what I should be deferring, and what I should just be executing.
I know there are other questions relating to this subject generally, but I'm afraid without a more relatable example I'm struggling to 'get it'.
My general understanding is that if the code being executed is non-trivial, then it's probably a good idea to async it, as to avoid it holding up someone else's session. There's clearly more to it than that, and callbacks get mentioned a lot, and I'm not 100% on why you wouldn't just synch everything. I've got some ways to go.
So here's some basic code I've put together in an express.js app:
app.get('/directory', function(req, res) {
process.nextTick(function() {
Item.
find().
sort( 'date-modified' ).
exec( function ( err, items ){
if ( err ) {
return next( err );
}
res.render('directory.ejs', {
items : items
});
});
});
});
Am I right to be using process.nextTick() here? My reasoning is that as it's a database call then some actual work is having to be done, and it's the kind of thing that could slow down active sessions. Or is that wrong?
Secondly, I have a feeling that if I'm deferring the database query then it should be in a callback, and I should have the actual page rendering happening synchronously, on condition of receiving the callback response. I'm only assuming this because it seems like a more common format from some of the examples I've seen - if it's a correct assumption can anyone explain why that's the case?
Thanks!
You are using it wrong in this case, because .exec() is already asynchronous (You can tell by the fact that is accepts a callback as a parameter).
To be fair, most of what needs to be asynchronous in nodejs already is.
As for page rendering, if you require the results from the database to render the page, and those arrive asynchronously, you can't really render the page synchronously.
Generally speaking it's best practice to make everything you can asynchronous rather than relying on synchronous functions ... in most cases that would be something like readFile vs. readFileSync. In your example, you're not doing anything synchronously with i/o. The only synchronous code you have is the logic of your program (which requires CPU and thus has to be synchronous in node) but these are tiny little things by comparison.
I'm not sure what Item is, but if I had to guess what .find().sort() does is build a query string internally to the system. It does not actually run the query (talk to the DB) until .exec is called. .exec takes a callback, so it will communicate with the DB asynchronously. When that communication is done, the callback is called.
Using process.nextTick does nothing in this case. That would just delay the calling of its code until the next event loop which there is no need to do. It has no effect on synchronicity or not.
I don't really understand your second question, but if the rendering of the page depends on the result of the query, you have to defer rendering of the page until the query completes -- you are doing this by rendering in the callback. The rendering itself res.render may not be entirely synchronous either. It depends on the internal mechanism of the library that defines the render function.
In your example, next is not defined. Instead your code should probably look like:
app.get('/directory', function(req, res) {
Item.
find().
sort( 'date-modified' ).
exec(function (err, items) {
if (err) {
console.error(err);
res.status(500).end("Database error");
}
else {
res.render('directory.ejs', {
items : items
});
}
});
});
});

How do you instruct mocha/nodejs to wait till all db operations are over

I'm trying to test if some of my db operations are executed properly. The flow is as follows (I'm using mocha for testing)
Call code which loops through data and saves it to redis
Get data from redis (in my testcase) to see if it saves the right data.
I'm noticing that the get data from db gets executed much before anything is saved. I was looking at the done() option in mocha, however that seems to work only if data is saved through mocha (setup etc).
So how do I instruct mocha to wait for all db to be saved before trying to retrieve from db?
Thanks for any help
dankohn is correct. Here's what you need to do, a bit more fleshed out:
describe('Your test', function () {
before(function (done) {
Your.redis.db.call.here(your, parameters, function (err) {
...you may want to check for errors first...
done();
});
});
it('should do what you wanted...', function (done) {
...your test case...
done();
});
});
Your redis call most likely provides a callback function as a parameter. That callback function is executed when the redis call is completed. Within that callback function, call done(). The data you wrote will be there throughout your tests.
You just need to write a before function with the parameter done in mocha to load the data into the database. As a callback for when your data is loaded, call done(). Now, all your data will load before your first test.

Resources