当我第二次 运行 我的测试时,为什么我在 Mongoose 中出现错误 "Cannot overwrite model once compiled"?

Why do I get error "Cannot overwrite model once compiled" in Mongoose when I run my test a second time?

我已阅读相关内容post:Cannot overwrite model once compiled Mongoose

问题是这些解决方案都没有帮助我解决问题。

我得到标题中的错误,我有以下设置:

文件夹结构:

我的模型是这样的:

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: Cannot overwrite forums model once compiled.

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

我已经解决了问题。

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

"test": "mocha --watch"

这是错误。我认为 --watch 不会重新实例化所有内容,就像 "Hot Module Replacement".

我安装了 nodemon 并像这样更改了我的测试脚本:

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

这可以确保重新运行整个文件并且不会出现错误。

另一个应该有效的相关 post:mocha --watch and mongoose models

还有另一种方法可以解决这个问题并继续使用 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
}

假设您有一个模型 'User'。您必须使用上述功能导出它:

const userSchema = {...}

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

现在,当您想要导入模型时,您可以调用以下函数:

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

我建议你有一个更简单的方法,就是在测试完成后删除模型 运行。

这里是:

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

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

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

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

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