rewiremock icon indicating copy to clipboard operation
rewiremock copied to clipboard

Something like cache problem

Open polizinha opened this issue 3 years ago • 3 comments

Hi! I'm mocking mongodb in my mocha tests with rewiremock and mongo-mock. I can rewire my wrapper that contains the mongo lib, but when another module calls that file, it doesn't have the started configuration like database, collections... I think it's something like cached modules, but I don't know what to do anymore. I have:

common.js

  require('app-module-path').addPath(`${process.cwd()}/src`);
  global.rewiremock = require('rewiremock').default;
  const {addPlugin, plugins} = require('rewiremock');
  addPlugin(plugins.usedByDefault);
  addPlugin(plugins.nodejs);
  global.TestDbHelper = require('./dbHelper');

dbHelper.js

  const mongoMock = require('mongo-mock');
  class TestDbHelper {
    constructor() {
      this.mongodb = rewiremock.proxy('lib/mongo', {
        'mongodb': mongoMock
      });
   }
    async connect() {
      rewiremock.enable();
      await this.mongodb.connect('mongodb://localhost:27017/test', { db: 'test' });
    }
    async disconnect() {
      rewiremock.disable();
    }
  }

lib/mongo.js

const { MongoClient, ObjectID } = require('mongodb');
const config = require('config');
const mongoConfig = config.get('mongodb');

module.exports = {
  async connect (uri, options = {}) {
    return new Promise(async (resolve, reject) => {
        this.uri = uri;
        this.client = await MongoClient.connect(uri, {
          useNewUrlParser: true,
          useUnifiedTopology: true,
          ...options
        })
        this.db = this.client.db()
        return resolve(this.client);
    })
  },
  async getCollection (name) {
    if (!this.client || !this.client.isConnected()) {
      await this.connect(this.uri)
    }
    return this.db.collection(name)
  }
}

When the feature that is being tested calls getCollection, this.client is undefined and all will fail.

CALLER:     at TestDbHelper.connect
  mongo-mock:mongo_client connecting localhost:27017/test +0ms
  mongo-mock:collection initializing instance of `system.namespaces` with 1 documents +1ms
  mongo-mock:collection initializing instance of `system.indexes` with 0 documents +0ms
  mongo-mock:db test open +353ms
  mongo-mock:collection initializing instance of `system.namespaces` with 1 documents +1ms
  mongo-mock:collection initializing instance of `system.indexes` with 0 documents +0ms
  app:mongo:connector MongoDB Connected +0ms
CALLER: getCollection
(node:9060) UnhandledPromiseRejectionWarning: MongoParseError: URI malformed, cannot be parsed
supressed...
  mongo-mock:db undefined open +93ms

Can you help me?

polizinha avatar Mar 24 '21 00:03 polizinha

rewiremock.enable(); / rewiremock.disable(); are definetely not working as you might expected them, as 1) they have nothing to do 2) they react only to require call between them, which is not happening.

Actually, from what I can see 'mongodb has got replaced by mongoMock. So what is not working in this case?

theKashey avatar Mar 24 '21 03:03 theKashey

In the log, we can see connection (caller TestDbHelper.connect), after this, my test that calls getCollection. In this point, we don't have this.client and this.uri anymore (populated in connection). So, he tried to connect again and use undefined this.uri and we will have a failure.

I tested that flow without rewiremock (using conditionals with process.env.NODE_ENV inside code) and It worked. So, I think I'm doing something wrong with rewiremock.

polizinha avatar Mar 24 '21 13:03 polizinha

Sorry. The actual test is not visible to me and there is no way I can help here:

  • what calls getCollection?
  • what initializes TestDbHelper? How it's been used?
  • the only way to set this.url is to call connect, the logic in getCollection just cannot work!

theKashey avatar Mar 25 '21 03:03 theKashey