theKashey / rewiremock

The right way to mock dependencies in Node.js or webpack environment.
MIT License
492 stars 30 forks source link

Something like cache problem #128

Open polizinha opened 3 years ago

polizinha commented 3 years ago

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?

theKashey commented 3 years ago

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?

polizinha commented 3 years ago

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.

theKashey commented 3 years ago

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