How to avoid timeouts in mocha testcases? - node.js

Here I am attaching my code, I am passing done callback and using supertest for request. Since I am using assert/expect in my testcase inside request.end block why I need to worry about timeout? What is mistake I am making here.
it('should get battle results ', function(done) {
request(url)
.post('/compare?vf_id='+vf_id)
.set('access_token',access_token)
.send(battleInstance)
.end(function(err, res){ // why need timeout
if (err) return done(err);
console.log(JSON.stringify(res.body));
expect(res.body.status).to.deep.equal('SUCCESS');
done();
});
});
Testcase results following response:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
If I am running my testcases with mocha command then its show this error while If I am running test mocha --timeout 15000 then testcase is passing correctly. But I want to avoid timeout, How can I do that?

If I am running my testcases with mocha command then its show this error while If I am running test mocha --timeout 15000 then testcase is passing correctly. But I want to avoid timeout, How can I do that?
You can't avoid timeouts, since it looks like you're testing a remote service. If, for whatever reason, the request to that service takes a long time, you will run into timeouts.
You can tell Mocha to disable for timeout checking by setting the timeout to 0, but that's probably also not ideal because it may cause each test case to take an excessive amount of time.
As an alternative, you can mock request (which I assume is superagent) so you can control the entire HTTP request/response flow, but since it looks like you're testing a remote service (one which you have no control over) that would make this particular test case moot.

In mocha a default timeout of 2 seconds (2000ms) is set by default.
You can extend the default (global) timeout from the command line using the --timeout xxxx flag.
If you want instead to change the timeout for a specific test case you can use the this.timeout( xxxx ) function - note it does not work for arrow functions - (where xxxx is a number like 20000 representing milliseconds).
it('My test', function(){
this.timeout(5000);
//... rest of your code
});
You can also set a timeout of a set of test cases (wrapped by a describe):
describe("My suite", function(){
// this will apply for both "it" tests
this.timeout(5000);
it( "Test 1", function(){
...
});
it( "Test 2", function(){
...
});
});
It also works for before, beforeEach, after, afterEach blocks.
More documentation is available here: https://mochajs.org/#timeouts
Consider that 2 seconds is usually a good amount of time to run your tests so I would say that extend the default timeout should be an exception, not the common rule in your tests.
Also if your test is not async and you have to extend the timeout I would strongly suggest to review the function that is taking so long before extending the timeout.

Mocha : Timeouts
Test-specific timeouts may also be applied, or the use of this.timeout(0) to disable timeouts all together:
To disable the timeout from happening simply set it to 0. I use mocha <file> --timeout 0 when I'm debugging so the timeout error does not get thrown.

Here is what you need
mocha timeouts
describe('a suite of tests', function() {
this.timeout(500);
it('should take less than 500ms', function(done){
setTimeout(done, 300);
});
it('should take less than 500ms as well', function(done){
setTimeout(done, 250);
});
})

Related

jest method done() is not defined

I started using jest and I now need to test callbacks.
To know when a callback was called, the done() is supposed to be used accourding to the documentation: https://jestjs.io/docs/en/asynchronous.html
However the done() is not recognized beeing undefined and is consequently throwing this Error:
Test suite failed to run
TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
pathToErrorFile:line - error TS2304: Cannot find name 'done'.
63 done();
~~~~
//code to reproduce:
test('test', ()=>{
fkt(param, ()=>{
done();
});
});
I have setup jest with node and angular and in both projects this function does not exist.
So what I want to know is, where this function is even coming from and how I can troubleshoot it.
Note that everything else (test, describe, etc. ) is working fine done() as its exception.
done is not defined as a global var. You get it passed to the test function.
test('test', done => {
fkt(param, () => {
done();
});
});
Note that if you specify done parameter, jest will detect it and will fail the test on timeout, if the done function is not called after the test has finished.
If done() is never called, the test will fail (with timeout error), which is what you want to happen.
Then, you have to call done even if the test fails - otherwise you won't see the error.
If we want to see in the test log why it failed, we have to wrap expect in a try block and pass the error in the catch block to done. Otherwise, we end up with an opaque timeout error that doesn't show what value was received by expect(data).
See Jest - Testing Asynchronous Code

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

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)

Mocha & SuperTest Tests Timing out

I've got a problem whereas sometimes my tests fail due to the asserts being run before the response comes back here in my integration tests:
it('should find all countries when no id is specified', co.wrap(function *(){
var uri = '/countries';
var response = yield request.get(uri);
should.exist(response.body);
response.status.should.equal(200);
}));
Not sure how to tweak mocha or supertest to wait or if I should use a promise here or what. I'm using generators with mocha here.
Adding a longer timeout to mocha does absolutely nothing. The query behind this particular test takes a bit longer than my other tests. My other tests run just fine.

Kicking off mocha describes in parallel

I want to be able to have all my describe statements in Mocha get kicked off in parallel. Can someone help me figure out how to do that?
You can't do this directly with mocha because it creates a list of it() callbacks and invokes them in order.
mocha-parallel-tests can do this if you're willing to move your describes into separate .js files. To convince yourself, install it somewhere and invoke it with a short --slow so it reports each time:
laptop:/tmp/delme$ npm install mocha-parallel-tests
laptop:/tmp/delme$ cd node_modules/mocha-parallel-tests
laptop:/tmp/delme/node_modules/mocha-parallel-tests$ ./bin/mocha-parallel-tests test/parallel/tests --timeout 10000 --slow 100
You will see that it ran three (very simple) tests suites in the time it took to run the longest.
If your tests don't depend on side-effects of earlier tests, you can make them all asynchronous.
A simple way to do this is to initiate the stuff that takes a while before the describe and use the regular mocha apparatus to evaluate it. Here, I create a bunch of promises which take a while to resolve and then iterate through the tests again, examining their results in a .then() function:
var expect = require("chai").expect;
var SlowTests = [
{ name: "a" , time: 250 },
{ name: "b" , time: 500 },
{ name: "c" , time: 750 },
{ name: "d" , time:1000 },
{ name: "e" , time:1250 },
{ name: "f" , time:1500 }
];
SlowTests.forEach(function (test) {
test.promise = takeAWhile(test.time);
});
describe("SlowTests", function () {
// mocha defaults to 2s timeout. change to 5s with: this.timeout(5000);
SlowTests.forEach(function (test) {
it("should pass '" + test.name + "' in around "+ test.time +" mseconds.",
function (done) {
test.promise.then(function (res) {
expect(res).to.be.equal(test.time);
done();
}).catch(function (err) {
done(err);
});
});
});
});
function takeAWhile (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(time);
}, time);
});
}
(Save this as foo.js and invoke with mocha foo.js.)
Meta I disagree with the assertion that tests should be primarily be synchronous. before and after pragmas are easier but it's rare that one test invalidates all remaining tests. All discouraging asynchronous tests does is discourage extensive testing of network tasks.
Mocha does not support what you are trying to do out of the box. It runs tests sequentially. This has a big advantage when dealing with an unhandled exception: Mocha can be sure that it happened in the test that it is currently running. So it ascribes the exception to the current test. It is certainly possible to support parallel testing but it would complicate Mocha quite a bit.
And I tend to agree with David's comment. I would not do it. At the level at which Mocha usually operates, parallelism does not seem to me particularly desirable. Where I have used test parallelism before is at the level of running end-to-end suites. For instance, run a suite against Firefox in Windows 8.1 while at the same time running the same suite against Chrome in Linux.
Just to update this question, Mocha version 8+ now natively supports parallel runs. You can use the --parallel flag to run your tests in parallel.
Parallel tests should work out-of-the box for many use cases. However, you must be aware of some important implications of the behavior
1 thing to note, some reporters don't currently support this execution (mocha-junit-reporter for example)
If you are using karma to start your tests, you can use karma-parallel to split up your tests across multiple browser instances. It runs specs in different browser instances in parallel and is very simple and easy to install:
npm i karma-parallel
and then add the 'parallel' to the frameworks list in karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ['parallel', 'mocha']
});
};
karma-parallel
Disclosure: I am the author

Setting timeouts with supertest not working

I'm trying to test my server with some code like so:
describe 'POST /do/some/stuff/', ->
it 'should do this thing', (done) ->
request app
.post '/do/some/stuff/'
.timeout 10000
.expect 200
.end (err, res) ->
return done err if err?
done()
The thing that the server is doing usually takes a few seconds, which is longer than the default timeout of 2000ms, so I call .timeout 10000. However, despite this, when I run the code I get:
1) POST /do/some/stuff/ should do this thing:
Error: timeout of 2000ms exceeded
What do I need to do to increase this timeout?
Changing the timeout on your request object does not change anything to Mocha's default timeout. Doing this.timeout(10000) (whatever the CoffeeScript equivalent is) inside your test should take care of that.
You can specify the timeout when running your test framework. For instance for mocha it would be like mocha -t 7000 . Alternatively, you can add a test with setTimeout just to create a delay (if the required delay is in between tests).

Resources