0

I am testing a HTTP Request in MEAN-Stack with Mocha/supertest/expect library, that takes 4 seconds to return:

it('should return product data', (done) => {
    request(app)
    .get('/P/Product')
    .expect(200)
    .expect((res) => {
        expect(res.body[0]._id).toEqual('123456789')
    })
    .end(done);
});

The function should execute the "done" callback at the end, after the HTTP Request finished. But I am getting error:

1) should return product data:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a
Promise, ensure it resolves. 

I think it works with unnested expect-calls. How would I do it with nested expect-calls inside other expect-calls, like in the example abouve?

pynexj
  • 19,215
  • 5
  • 38
  • 56
MMMM
  • 3,320
  • 8
  • 43
  • 80

2 Answers2

2

Maybe the response time from the request is too high and causing Mocha's default 2 second test timeout to happen. Possibly try a cURL to the url from CLI to see what timing you get back or up the mocha test time threshold for the test.

describe('testing', function() {
    // This applies the timeout of 5 seconds to each test.
    this.timeout(5000);

    it('should return product data', function() {
       // This applies a timeout of 5 seconds for this test only
       this.timeout(5000);
       request(app)
           .get('/P/Product')
           .expect(200)
           .expect((res) => {
                expect(res.body[0]._id).toEqual('123456789')
           })
           .end(done);
       });
});

Another way would to use the promise approach if you thing the chain of expect calls is causing timeout issues.

it('should return product data', () => {
   request(app)
   .get('/P/Product')
   .then((res) => {
       expect(res.status).to.equal(200);
       expect(res.body[0]._id).to.equal('123456789');
   })
});
Andrew Nolan
  • 1,987
  • 2
  • 20
  • 23
  • hmm can you give me an example how to set up mocha test time threshold? beforeEach(function(done) { this.timeout(3000); setTimeout(done, 3000); this does not work... – MMMM Oct 26 '18 at 15:03
  • i edited my answer to provide examples of how to use set the time out on the suite level or at the individual test level – Andrew Nolan Oct 26 '18 at 15:12
  • hey, thanks for the example, I tried the same in my code, but I get: TypeError: this.timeout is not a function... I googled about it and it seems many other have the same problem, is there a workaround for this? it actually works globally if you run mocha with timout option: "mocha --timeout 15000" but not on test unit level... – MMMM Oct 26 '18 at 15:16
  • odd, this works for me in my own tests when its expect to exceed 2 seconds. Per mocha docs, this is the way to do it as well for timeouts – Andrew Nolan Oct 26 '18 at 15:23
  • hmmm I got weird behaviour... It's possible to chain ".timeout(2000)" and it does not complain, however, it seems that was not the problem. It was actually waiting for " DB connection alive" which caused the problems... the making of the connection apparently took so long, that the async request from the test run already called the data from database before any connection was built up... so timeout had no effect, the request itself took around 50ms. However, I used a timeout >2000ms in one request, and I still got no workaround how to accept more than 2000ms timeout... – MMMM Oct 26 '18 at 15:45
  • one more question.. did you use any imports before you used this.timout() ? – MMMM Oct 26 '18 at 15:47
  • nope. `this` is in reference to the test or test suite that is part of mocha – Andrew Nolan Oct 26 '18 at 18:29
  • 1
    You're probably using arrow functions on `describe` that's why `this.timeout` is not defined. Use `describe('title', function() {...}` instead of `describe('title',() => {...}` – nicholaswmin Oct 27 '18 at 14:15
  • @Nicholas Kyriakides, you are actually correct, I used normal callback function: it('should async square a number', function(done) { this.timeout(2005); utils.asyncSquare(5, (res) => { expect(res).toBe(25).toBeA('number'); done(); }); }); and it worked with the timeout... – MMMM Oct 27 '18 at 20:08
-1

I got the solution, the problem was the use of arrow function: (done)=>{...}, instead of normal callback, it works like this:

it('should async square a number', function(done) {  
    this.timeout(2005);
    utils.asyncSquare(5, (res) => {
      expect(res).toBe(25).toBeA('number');
      done();
    });
  });

or it also works if you set timeout globally in the package test script:

"test": "mocha --timeout 3000 **/*.test.js",
MMMM
  • 3,320
  • 8
  • 43
  • 80
  • It's @AndrewNolan that answered the crux of your question (use `.timeout`) so I'd advise you delete your answer and accept his instead. The fact that you were using arrow functions is tangential to the original problem you had. – nicholaswmin Oct 27 '18 at 20:11
  • the solution from @AndrewNolan doesn't work like he showed, you need to use a normal callback function(done) inside the it function, but thanks for the minus... – MMMM Oct 27 '18 at 20:14
  • No problem, I'd happily do it again for anyone who scorns the work done by others to help him just because he didn't know how to use an arrow function. – nicholaswmin Oct 27 '18 at 20:15
  • hmm you are actually right, I just tested it again and it worked. I placed my closing brackets from top level describe wrongly, that was the issue.. sorry about that, no reason to be rude, dude ;) – MMMM Oct 27 '18 at 20:21
  • You are missing the point here. @AndrewNolan told you about the `timeout` which you didn't know about previously. That's the answer. How to get `timeout` working is tangential to the question. If you think his answer can be improved, then edit it but still accept it. Nobody is getting paid for helping you out with your problems, the least you can do is show that you appreciate the efforts by properly awarding reputation. – nicholaswmin Oct 27 '18 at 20:39
  • how should I know if it's the correct answer if it does not work? And should I accept uncorrect answers or just accept any answer being thrown at me without knowing if its correct? Your answer makes no sense... – MMMM Oct 28 '18 at 09:17
  • Ok, so with my suggestion under Andrew's comment you made it work. So you knew it was the timeout. Nevertheless you went ahead after that fact and wrote your own answer based on the exact same suggestion that Andrew made. Now you are tiring me out. If you still don't get what I'm trying to point out to you, then I rest my case and this would be my last comment. – nicholaswmin Oct 28 '18 at 10:49
  • I just don't get it why u make so much fuss about it, my intention is not to steal s.o. credits, I am just trying to understand the topic inherently, at first it wasnt working with Andrews solution for me, then I discovered I had typos, but now I am even not sure about that anymore as my database has inconsistent behaviour. At the first initiation (or after sleep wakeup?) my db always needs longer than 2 seconds initial for any requests, after retry of test it goes under 50ms... but besides that, this is really an annoying thing on SO here, many ppl are rude on "stupid" questions... – MMMM Nov 03 '18 at 20:36
  • ...and banning users just seems to be a matter of time – MMMM Nov 03 '18 at 20:36