Mongoose Schema.index on multiple fields does not work with tests

212 views Asked by At

I have created an uploadSchema (mongoose.Schema) with the fields (among the rest): key and bucket. each of them alone is not unique but together I want them to create a unique id. in my code, I used the line (right after declaring the uploadSchema and right before the uploadModel):

uploadSchema.index({ key: 1, bucket: 1 }, { unique: true, background: true });

but then, in my tests (mocha and chai), the indexing is not enforced, and so I can create two instances with the same key and bucket (in my case). for example, in my code:

await uploadModel.create({ key: testUpload.key, bucket: testUpload.bucket, 
name: 'name1',  ownerID: USER.id, parent: null }).should.eventually.exist;

and right after that:

await uploadModel.create({key: testUpload.key, bucket: testUpload.bucket,
 name: 'name1', ownerID: USER.id, parent: null }).should.eventually.be.rejected;

does not throw the right error error:

AssertionError: expected promise to be rejected but it was fulfilled with { Object ($__, isNew, ...) }

Am I not using it correctly? Or is there a problem with indexing and testing?

2

There are 2 answers

0
Shahar On BEST ANSWER

so I figured it out! Apparently, I used mongoose.connection.dropDatabase(); in my afterEach of the tests. That means that the indexes were reset each time. So what I did was to recreate the indexes each time in my tests:

  before(async () => {
    // Remove files from DB
    const collections = ['files', 'uploads'];
    for (const i in collections) {
      mongoose.connection.db.createCollection(collections[i], (err) => {});
    }
    await mongoose.connection.collections['files'].createIndex({ name: 1, parent: 1, ownerID: 1 }, { unique: true });
    await mongoose.connection.collections['uploads'].createIndex({ key: 1, bucket: 1 }, { unique: true });
  });

And in the beforeEach:

  beforeEach(async () => {
    const removeCollectionPromises = [];
    for (const i in mongoose.connection.collections) {
      removeCollectionPromises.push(mongoose.connection.collections[i].deleteMany({}));
    }
    await Promise.all(removeCollectionPromises);
  });

afterEach is empty. now it works :)

2
Tom Slabbaert On

Most likely you set autoIndex to false in your connection (which is recommended to do).

Either add it to you Schema:

let uploadSchema = mongoose.Schema({ ... }, {autoIndex: true});

But i would recommend just building the index yourself on the database, i think its the safest way around it.