1

Edit - It seems I had two issues here. I have accepted the answer given below but please read the comments because the mocha -w issue was just as significant in the fix.

I've read a few SO questions and answers on this and tried a few of the suggested methods but I'm still not able to resolve this issue so I'm hoping someone can help me:

I have a model:

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const slug = require('slugs');

const storySchema = new mongoose.Schema({
  name :{
    type: String,
    trim: true,
    required: 'Please enter a store name'
},
  slug: String,
  storyText: {
    type: String,
    trim:true
},
  keyStageLevel: [String]
});


module.exports = mongoose.model('Story', storySchema);

and a storyController:

const mongoose = require('mongoose');
const Story = mongoose.model('Story');

exports.storyHomePage = (req, res) => {
console.log(req.name);
res.render('story', {
    title:"Reading Project = Story Home Page",
    created:req.query.created

  });
};

and I have mocha running some tests. However when I run the test I get an error

MissingSchemaError: Schema hasn't been registered for model "Store".

Reading this https://stackoverflow.com/a/21915511/1699434 I can modify my storyController to

const mongoose = require('mongoose');

mongoose.model('Story', new mongoose.Schema());

const Story = mongoose.model('Story')

which keeps Mocha happy but then nodemon blows up with an error

OverwriteModelError: Cannot overwriteStorymodel once compiled.

Looking around this https://stackoverflow.com/a/19051909/1699434 seems like the go to answer for this issue but as far as I can see I'm using that approach (I use const Store = mongoose.model('Store'); instead of const Store = require('../models/Store'))

So I'm a bit stuck. Any help much appreciated!

Edit to include start.js

const mongoose = require('mongoose');


// import environmental variables from our variables.env file
require('dotenv').config({ path: 'variables.env' });

// Connect to our Database and handle any bad connections
mongoose.connect(process.env.DATABASE);
mongoose.Promise = global.Promise; // Tell Mongoose to use ES6 promises
mongoose.connection.on('error', (err) => {
  console.error(`${err.message}`);
});

//import all of the models
require('./models/Story');

// Start app
const app = require('./app');
app.set('port', process.env.PORT || 7777);
const server = app.listen(app.get('port'), () => {
console.log(`Express running → PORT ${server.address().port}`);
});
Stuart Brown
  • 977
  • 2
  • 22
  • 47

1 Answers1

0

You should import the Story model using the following syntax, And there is no need to import mongoose module again:

// I suppose the file is located in 'models' folder and the current folder is 'controllers'
const Story = require('../models/story');

By doing const Story = mongoose.model('Story'); you are creating a Story model without a schema definition and that's why you get Schema hasn't been registered for model "Store".

In you second example:

// this create a new model from an empty schema (schema without fields)
mongoose.model('Story', new mongoose.Schema());

// overwriting the first model which is not allowed by mongoose
const Story = mongoose.model('Story')

Remember that mongoose.model() method only defines model from schema that maps to a MongoDB collection

YouneL
  • 8,152
  • 2
  • 28
  • 50
  • many thanks for your quick reply. So I've changed the controller to just `const Story = require('../models/Story');` but testing still throws `OverwriteModelError: Cannot overwrite `Story` model once compiled.` – Stuart Brown Jan 16 '18 at 20:39
  • I think maybe you forget to remove this line `mongoose.model('Story', new mongoose.Schema());` or `mongoose.model('Story');` in your controller or in an imported module, it should appear only once in the schema definition – YouneL Jan 16 '18 at 22:08
  • Thanks YouneL :). I have a start.js file (I edited the question above to show it) which imports the models too. If I comment out `require('./models/Story');` in start.js and just have `const Story = require('../models/Story');` then Nodemon is happy but Mocha complains about `OverwriteModelError: Cannot overwrite `Story` model once compiled.` – Stuart Brown Jan 16 '18 at 22:30
  • Maybe you should remove this line `require('./models/Story');` from `start.js`, and in the storyController keep only this: `const Story = require('../models/story');` and remove all `mongoose.model(...)` – YouneL Jan 16 '18 at 23:13
  • There is another thing, replace `mongoose.model(...)` by `require('..')` in Mocha too – YouneL Jan 17 '18 at 10:57
  • Thanks @YouneL. The tests that I have written don't explicitly seek to test my Schemas/models, they are currently concerned with testing HTTP status codes from particular routes / Controllers (which reference the models as above). It seems however that as soon as I require the server in my Mocha tests (something like `const server= require('./app');` that Mocha starts reporting the issues above. Generally I'm pretty certain your answer is right so I expect to mark it as such after I do some more digging this evening :) – Stuart Brown Jan 17 '18 at 11:40
  • Thanks @StuartBrown I hope you will find the answer, for me I never used mocha or another testing framework, I read about it but i never use it – YouneL Jan 17 '18 at 13:53
  • marking your answer as correct because my code was certainly wrong in the ways that you pointed out. However just fixing as per your guidance wasn't enough, there is also an issue with mocha watch (mocha -w) as discussed here https://github.com/Automattic/mongoose/issues/1251#issuecomment-11466245 and here https://github.com/mochajs/mocha/issues/747 on the mongoose repo. – Stuart Brown Jan 17 '18 at 21:38