Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: <function> is not a function (Only interacting with Mongoose) #3565

Closed
MrCerealKiller opened this issue Nov 11, 2018 · 1 comment
Assignees
Labels
invalid not something we need to work on, such as a non-reproducing issue or an external root cause type: question support question

Comments

@MrCerealKiller
Copy link

Prerequisites

  • [ x] Checked that your issue hasn't already been filed by cross-referencing issues with the faq label
  • [ x] Checked next-gen ES issues and syntax problems by using the same environment and/or transpiler configuration without Mocha to ensure it isn't just a feature that actually isn't supported in the environment in question or a bug in your code.
  • [ x] 'Smoke tested' the code to be tested by running it outside the real test suite to get a better sense of whether the problem is in the code under test, your usage of Mocha, or Mocha itself
  • [ x] Ensured that there is no discrepancy between the locally and globally installed versions of Mocha. You can find them with: node node_modules/.bin/mocha --version(Local) and mocha --version(Global). We recommend avoiding the use of globally installed Mocha.

Description

I'm using mocha to test some CRUD functions for my Mongoose models. One is System, then two very similar models for an I[input]Sector and an O[utput]Sector. I can assure that all the models exist as do the functions I'm calling in the test.

What is failing is the following test (note that in a top-level test file I'm connecting to the database and I drop collections between each test):

describe('Delete', function() {
    before('setting constants', function() {
      this.fakeId = '5be16a873dde9a64dbedac38';
      this.systemId  = null;
      this.oSectorId = null;
      this.iSectorId = null;
    });

    beforeEach('creating test objects', function(done) {
      var that = this;
      var oSector = new OSector({
        name: 'Output Sector',
        system: that.fakeId,
        type: 'Water',
        key: 1
      });

      oSector.save(function(err, oSector) {
        that.oSectorId = oSector._id;
        var iSector = new ISector({
          name: 'Input Sector',
          system: that.fakeId,
          type: 'Temperature',
          key: 1
        });

        iSector.save(function(err, iSector) {
          that.iSectorId = iSector._id;
          var system = new System({
            name: 'TestSystem',
            passcode: 'test',
            inputPort: '/dev/ttyUSB0',
            inputSectors: [that.iSectorId],
            outputPort: '/dev/ttyUSB1',
            outputSectors: [that.oSectorId]
          });

          system.save(function(err, system) {
            that.systemId = system._id;
            done()
          });
        });
      });
    });

    // Remove system by ID -----------------------------------------------------
    describe('#removeSystemById', function() {
      context('Valid', function() {
        it('should pass and remove a system and its sectors', function(done) {
          var that = this;
          System.removeSystemById(that.systemId, function(err, ret) {
            assert.isNull(err, 'expected no error; returned error');
            assert.isNotNull(ret, 'expected system; returned none');
            assert.instanceOf(ret, System, 'object was not of type System');
            assert.equal(ret.name.toString(),
                         that.validName1.toString(),
                         'unexpected name');
            done();
          });
        });
      });
    });
  });

(Feel free to skip the next two blocks of code because they are mostly for context)
For more context, here is the function it is calling in the model:

module.exports.removeSystemById = function(id, callback) {
  System.findById(id, function(err, system) {
    if (err) {
      callback(err, null);

    } else if (system == null) {
      callback(null, null);

    } else {
      // Remove all of the children input sectors
      system.inputSectors.forEach(function(sector) {
        ISector.removeISectorById(sector, function(err) {
          if (err) {
            throw err;
          }
        });
      });

      // Remove all of the children output sectors
      system.outputSectors.forEach(function(sector) {
        OSector.removeOSectorById(sector, function(err) {
          if (err) {
            throw err;
          }
        });
      });

      system.remove(callback);
    }
  });
};

And for more context, here is the function defined in one of the sector models (they're pretty incredibly similar to each other):

module.exports.removeISectorById = function(id, callback) {
  ISector.findById(id, function(err, sector) {
    if (err) {
      callback(err, null);

    } else if (sector == null) {
      callback(null, null);

    } else {
      // Remove all of the child input events
      // and remove their reference from their input sector
      var query = {_id: sector._id};
      ISector.findOne(query).populate('iEvents').exec(function(err, sector) {
        if (err) {
          throw err;
        }

        sector.iEvents.forEach(function(iEvent) {
          IEvent.findOne(iEvent).populate('target').exec(function(err, iEvent) {
            var idx = iEvent.target.iEvents.indexOf(iEvent._id);
            if (idx > -1) {
              iEvent.target.iEvents.splice(idx, 1);
              iEvent.target.save(function(err, iEvent) {
                if (err) {
                  throw err;
                }
              });
            }
          });

          IEvent.removeIEventById(iEvent._id, function(err) {
            if (err) {
              throw err;
            }
          });
        });
        sector.remove(callback);
      });
    }
  });
};

As mentioned the actual implementation isn't incredibly important and may be difficult to understand without going through the rest of the code; however, I've already tested it at a higher level using the HTTP requests these functions are called from. What is strange though is that when I try to run this in Mocha, it throws this error:

Uncaught TypeError: ISector.removeISectorById is not a function
at /home/jeremy/projects/seedlink/models/system.js:134:17
at Array.forEach()
at /home/jeremy/projects/seedlink/models/system.js:133:27
at /home/jereny/projects/seedlink/node_modules/kareem/index.js:273:21
at /home/jereny/projects/seedlink/node_modules/kareem/index.js:131:16
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)

Steps to Reproduce

  1. Open a connection to MongoDB through mongoose in a before() hook
  2. Run the single test as given above

(I'm honestly not sure how to simplify the case any more than that without starting a whole new project)

Expected behavior: [What you expect to happen]
Runs the function as referenced and throws errors only within the scope of the test.

Actual behavior: [What actually happens]
Throws an invalid type answer --not finding a function that was defined.

Reproduces how often: [What percentage of the time does it reproduce?]
100%

Versions

  • Mocha version: 5.2.0 (local dev-dependency | no global)
  • Node version: v9.2.1
  • System: Linux 4.4.0-138-generic Visual bug when emitting error #164-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux
  • Shell: zsh

I'm not even far enough into development to have integrated things like webpack, transpilers, gulp, etc. This is just using Mongoose (with Bluebird for the promise lib) and raw js.

Additional Information

If you could even give me some direction as to how to debug this, I can try looking into it myself.

Here's a link to my repo at the commit where I uploaded the issue-causing test

I'm hoping I'm just having a moment here and it's not a huge deal, so I'll be continuing to look through this. I'll close the issue if I find anything unrelated to Mocha. I chose to open the issue instead of going to StackOverflow because I noticed there were a couple other people that were experiencing similar issues, but always with 3rd-party apps in between. This strikes me as a simlar case using only Mocha, Mongoose, and Js.

@plroebuck plroebuck added type: question support question invalid not something we need to work on, such as a non-reproducing issue or an external root cause labels Nov 11, 2018
@plroebuck plroebuck self-assigned this Nov 11, 2018
@plroebuck
Copy link
Contributor

The error message: ISector.removeISectorById is not a function
Your code: var iSector = new ISector({
Your lib code: ISector.removeISectorById(sector, function(err) {

Should your library code be using the variable you created in your before?
This has nothing to do with Mocha...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid not something we need to work on, such as a non-reproducing issue or an external root cause type: question support question
Projects
None yet
Development

No branches or pull requests

2 participants