admin管理员组

文章数量:1390670

I'm testing a little node module with mocha and expect.js and I'm having a bit of a headache.

This is the test definition:

it('Should return an expansion array that contains all the objects that es along within a single group', function (done) {

  visibility.expand(data, config.data, panies, groups, function (error, expansion) {

    expect(error).to.be(null);
    expect(expansion).to.be.an('array');
    expect(expansion).to.have.length(2);
    expect(expansion.toString()).to.eql([testCompaniesIds[2], testCompaniesIds[3]].toString());

    done();
  });
});
  • data is a wrapper for database access and functionality. I initialize it in the before method of my test suite.
  • config.data holds an object with config params (not relevant)
  • panies is an array of strings
  • groups is an array of strings

The problem that i'm facing is that when Mocha reaches this line

expect(expansion).to.have.length(2);

and the length is different from 2, instead of throwing an error like: Expected 2 but length was 1 it simply stops and throw an error because of the timeout.

I verified that the test executed until that line.

A bit more of information: the method that I'm testing receives an array of pany names and an array of group names. Each group contains an array of pany database id's.

The expected behaviour of the method is to return an array with corresponding pany id's merged with the array of pany id's belonging to the group object.

Edit 2 due to possible duplicate: I was wrong. It was indeed executing in the scope of a promise.

Edit due to possible duplicate: the expectation in not executing in the scope of a promise (when using promises and executing expect in either resolve or reject functions is the promise who catch the error).

Thanks in advance!

I'm testing a little node module with mocha and expect.js and I'm having a bit of a headache.

This is the test definition:

it('Should return an expansion array that contains all the objects that es along within a single group', function (done) {

  visibility.expand(data, config.data, panies, groups, function (error, expansion) {

    expect(error).to.be(null);
    expect(expansion).to.be.an('array');
    expect(expansion).to.have.length(2);
    expect(expansion.toString()).to.eql([testCompaniesIds[2], testCompaniesIds[3]].toString());

    done();
  });
});
  • data is a wrapper for database access and functionality. I initialize it in the before method of my test suite.
  • config.data holds an object with config params (not relevant)
  • panies is an array of strings
  • groups is an array of strings

The problem that i'm facing is that when Mocha reaches this line

expect(expansion).to.have.length(2);

and the length is different from 2, instead of throwing an error like: Expected 2 but length was 1 it simply stops and throw an error because of the timeout.

I verified that the test executed until that line.

A bit more of information: the method that I'm testing receives an array of pany names and an array of group names. Each group contains an array of pany database id's.

The expected behaviour of the method is to return an array with corresponding pany id's merged with the array of pany id's belonging to the group object.

Edit 2 due to possible duplicate: I was wrong. It was indeed executing in the scope of a promise.

Edit due to possible duplicate: the expectation in not executing in the scope of a promise (when using promises and executing expect in either resolve or reject functions is the promise who catch the error).

Thanks in advance!

Share Improve this question edited Mar 30, 2015 at 12:00 javierfdezg asked Mar 20, 2015 at 8:35 javierfdezgjavierfdezg 2,1071 gold badge23 silver badges31 bronze badges 12
  • Have you tried with : expect(expansion.length).to.be(2) ? – Clément Berthou Commented Mar 20, 2015 at 13:42
  • Yes, the effect is the same if the length is not 2 – javierfdezg Commented Mar 20, 2015 at 15:24
  • And does test pass if you test every line one by one (by menting the others) ? Or if it doesn't, with which line does it fail ? – Clément Berthou Commented Mar 20, 2015 at 15:29
  • I just tried to remove all the expects except for that one and it fails with timeout. It's failing in the length line. – javierfdezg Commented Mar 20, 2015 at 17:52
  • Ok. So, the reason for a timeout, is that the done function is not called, or called after too long (I think 2 seconds is the default timeout setting on mocha). So either the callback is called after too long, the line is taking too much time/is stuck in an infinite loop or the done function is redefined at some point and the "correct" done function is not called. – Clément Berthou Commented Mar 20, 2015 at 18:57
 |  Show 7 more ments

3 Answers 3

Reset to default 2

You are executing the expectations in a callback function.

This means that the code is being executed in the visibility.expand method.

I'm pretty sure that the behaviour that you are seeing is because of the use of promises... are you using promises in the visibility.expand method?

Wrapping all the test between a try-catch like this:

it('Should return an expansion array that contains all the objects that es along within a single group', function (done) {

  visibility.expand(data, config.data, [testCompanies[0].name, testCompanies[1].name], [testGroups[0].name, testGroups[1].name], function (error, expansion) {
    try {
      expect(error).to.be(null);
      expect(expansion).to.be.an('array');
      expect(expansion).to.have.length(2);

      expect(checkIdIsContainedInArray(testCompaniesIds[0], expansion)).to.be(true);
      expect(checkIdIsContainedInArray(testCompaniesIds[1], expansion)).to.be(true);
      expect(checkIdIsContainedInArray(testCompaniesIds[2], expansion)).to.be(true);
      expect(checkIdIsContainedInArray(testCompaniesIds[3], expansion)).to.be(true);

      done();
    } catch (e) {
      done(e);
    }
  });
});

This test throws an error due to array length (is 4 and should be 2):

  Error: expected [ '464142414441464142414441',
  '464142414441464142414442',
  '464142414441464142414443',
  '464142414441464142414444' ] to have a length of 2 but got 4

Instead of:

Error: timeout of 2000ms exceeded

which can mean anything.

Debugging expect.js I saw that it was throwing an error but Mocha didn't manage to capture it.

Although this solution might not be as elegant as desired, at least it gives the desired feedback instead of a timeout.

I believe this is actually working as expected.

The Mocha tests are only able to end the async call when the done() is actually called. Since an error is thrown outside of the scope of the mocha execution context, it never reaches that block of code and the execution basically runs out of time.

I can't seem to find any official documentation stating this, but here's a few (somewhat related hopefully?) references -

https://github./pouchdb/pouchdb/issues/1339#issuement-34739526

http://chaijs./guide/styles/#expect //search around for error handling on callbacks

Is there a way to get Chai working with asynchronous Mocha tests?

Mocha failed assertion causing timeout

Edit - Actually, I'm seeing that I had it backwards, it should be catching the exception for sure. I would relook at the original code again and see if you have everything correct. Maybe update expect.js and see if it has some issues on your current version (or file a ticket). I use chai with the expect library and am able to get it to error fine. http://chaijs./

Code example with error being thrown correctly -

var chai = require('chai')
    , expect = chai.expect;

describe('something', function () {

    var j = [1];

    it('does something.. ', function (done) {
        setInterval(function () {
            console.log('its done');
            expect(j).to.be.length(2);
            done();
        }, 1000);
    });

});  

//Uncaught AssertionError: expected [ 1 ] to have a length of 2 but got 1

本文标签: javascriptMocha test timeouts when testing length of arrayStack Overflow