当我第二次运行测试时,为什么在Mongoose中出现错误“编译后无法覆盖模型”?

时间:2018-11-25 00:28:23

标签: node.js mongodb mongoose mocha

我已阅读相关文章:Cannot overwrite model once compiled Mongoose

这些解决方案都不能解决我的问题。

我得到标题错误,并且进行了以下设置:

文件夹结构:

enter image description here

我的模型如下:

  

forums.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const topicGroupSchema = require("./topicGroups");

const forumSchema = new Schema({
    title: String,
    topicGroups: [topicGroupSchema]
})

const Forum = mongoose.model("forums", forumSchema);

module.exports = Forum;
  

topicGroups.js

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const topicGroupSchema = new Schema({
    title: String,
   // Todo: add topics
})

module.exports = topicGroupSchema;

我的test_helper和saveForum_test.js文件如下:

  

saveForum_test.js

const assert = require("assert");
const Forum = require("../model/forums")

describe("Creating records", () => {
    it("can save a new forum", (done) => {
        const forum = new Forum({
            title: "CodeHUB"
        })
        forum.save()
            .then(() => {
                assert(forum.isNew)
                done();
            })
    })
})
  

test_helper.js

const mongoose = require("mongoose");
mongoose.Promise = global.Promise;

before(done => {
    mongoose.connect("mongodb://myuser:mypassword@ds221339.mlab.com:21339/clicker", { useNewUrlParser: true });
    mongoose.connection
        .once("open", () => {done()})
        .on("error", error => {
            console.warn("error", error)
        })
})

// FIXME: error when saved twice

beforeEach(done => {
    console.log(mongoose.connection.collections.forums)
    mongoose.connection.dropCollection("forums", () => {
        done();
    })
})

因此,当我使用Mocha运行测试套件时,一切都会按预期进行。 但是当我更改某些内容并再次运行时,出现错误

  

OverwriteModelError:编译后无法覆盖forums模型。

我将mlab与mongoose一起使用,而不是在本地安装的mongodb。也许与此有关吗?我想不通,我检查了所有文件和导入文件等10次,找不到错误,可以吗?

4 个答案:

答案 0 :(得分:1)

我在导出模型时解决了这个问题。

return mongoose.models[modelName] 
    ? mongoose.model(modelName)
    : mongoose.model(modelName, modelSchema)

答案 1 :(得分:0)

我已经解决了问题。

原来的问题是我如何运行测试套件。 我在npm run test中的package.json命令执行了以下操作:

"test": "mocha --watch"

这是错误。我认为--watch不能实例化所有内容,就像“热模块更换”一样。

我安装了nodemon并更改了测试脚本,如下所示:

"test": "nodemon --exec \"mocha -R min\""

这确保重新运行整个文件,并且没有出现错误。

另一个应该起作用的相关帖子:mocha --watch and mongoose models

答案 2 :(得分:0)

还有另一种解决方案,可以继续使用mocha --watch。

您可以使用像这样的函数来代替模型,因此模型不会被覆盖。

function loadModel(modelName, modelSchema) {
  return mongoose.models[modelName] // Check if the model exists
    ? mongoose.model(modelName) // If true, only retrieve it
    : mongoose.model(modelName, modelSchema) // If false, define it
}

假设您有一个模型“用户”。您必须使用上面的功能将其导出:

const userSchema = {...}

module.exports = () => loadModel('User', userSchema)

现在,当您要导入模型时,可以通过调用函数来完成该操作:

const User = require('../pathToTheModelLoaderFunction/user.js')()

答案 3 :(得分:0)

我建议您采用一种更简单的方法,即在测试运行后删除模型。

这里是:

after(() => {
    delete mongoose.connection.models['MyModelName'];
});

您也可以先添加它,以确保在没有现有模型的情况下开始所有测试。

Object.keys(mongoose.connection.models).forEach(modelName => {
    delete mongoose.connection.models[modelName]
})