Node.js 使用 Mongoose 进行测试。独特的被忽略

Node.js Testing with Mongoose. unique gets ignored

我的 mongoose 应用程序的集成测试遇到了一些麻烦。问题是,我的独特设置经常被忽略。架构看起来或多或少像这样(所以里面没有花哨的东西)

const RealmSchema:Schema = new mongoose.Schema({
    Title : {
        type : String,
        required : true,
        unique : true
    },    
    SchemaVersion : {
        type : String,
        default : SchemaVersion,
        enum: [ SchemaVersion ]
    }
}, {
    timestamps : {
        createdAt : "Created",
        updatedAt : "Updated"
    }
});

看起来基本上架构中设置的所有规则都被忽略了。我可以在需要字符串的地方传入 Number/Boolean。唯一有效的是未在模式中声明的字段不会保存到 db

第一个可能的原因:

我感觉,这可能与我的测试方式有关。我有多个集成测试。在每个数据库被删除之后(所以我对每个测试都有相同的条件,并在该测试中对数据库进行预处理)。

有没有可能是因为我的索引随数据库一起删除,而在下一个文本再次创建数据库和集合时没有重新启动?如果是这种情况,我如何确保在每次测试后我得到一个仍然符合我所有架构设置的空数据库?

第二个可能的原因:

我在这个项目中使用 TypeScript。也许定义模式和模型有问题。这就是我所做的。

1.创建架构(上面的代码)

2。为模型创建一个接口(其中 IRealmM 扩展了用于猫鼬的接口)

import { SpecificAttributeSelect } from "../classes/class.specificAttribute.Select";
import { SpecificAttributeText } from "../classes/class.specificAttribute.Text";
import { Document } from "mongoose";

interface IRealm{
    Title : String;
    Attributes : (SpecificAttributeSelect | SpecificAttributeText)[];
}

interface IRealmM extends IRealm, Document {

}

export { IRealm, IRealmM }

3。创建模型

import { RealmSchema } from '../schemas/schema.Realm';
import { Model } from 'mongoose';
import { IRealmM } from '../interfaces/interface.realm';


// Apply Authentication Plugin and create Model
const RealmModel:Model<IRealmM> = mongoose.model('realm', RealmSchema);

// Export the Model
export { RealmModel }

Unique 选项不是验证器。从 Mongoose 文档中查看 this link。

好的,我终于明白了。这里描述了关键问题

Mongoose Unique index not working!

Solstice333 在他的回答中指出 ensureIndex 已被弃用(我收到警告已经有一段时间了,但我认为它仍然有效)

在模型中添加 .createIndexes() 后,我得到了以下代码,它可以正常工作(至少在我没有测试的情况下是这样。代码后面有更多内容)

// Apply Authentication Plugin and create Model
const RealmModel:Model<IRealmM> = mongoose.model('realm', RealmSchema);
RealmModel.createIndexes();

现在的问题是,当你第一次建立连接时,索引会被设置,但如果你在你的进程中删除数据库则不会(至少对我来说,每次集成测试后都会发生)

因此在我的测试中,resetDatabase 函数将如下所示,以确保所有索引都已设置

const resetDatabase = done => {
    if(mongoose.connection.readyState === 1){
        mongoose.connection.db.dropDatabase( async () => {
            await resetIndexes(mongoose.models);
            done();
        });
    } else {
        mongoose.connection.once('open', () => {
            mongoose.connection.db.dropDatabase( async () => {
                await resetIndexes(mongoose.models);
                done();
            });  
        });      
    }
};

const resetIndexes = async (Models:Object) => {
    let indexesReset: any[] = [];
    for(let key in Models){
        indexesReset.push(Models[key].createIndexes());
    }
    Promise.all(indexesReset).then( () => {
        return true;
    });   
}