theKashey / rewiremock

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

Mocking non existent modules #130

Open Saif-Shines opened 3 years ago

Saif-Shines commented 3 years ago

This would appear like a weird use case, but I am currently struggling to pass through since a few days now.

run.js looks like this

requires /path/config.js
|
|
v
config.js requires app.js
|
|
V
let global.PATH = process.cwd();
app.js requires `${global.PATH}/lib/utils/data-util`

run.test.js

So far working with rewiremock, I broadly understood, it resolves and then mocks all the dependencies (node, npm). Only by the time rewiremock.enable() is invoked, all the mocks are replaced for specified test case until rewiremock.disable()

run.js indirectly requires `${global.PATH}/lib/utils/data-util`

so,

rewiremock(`${global.PATH}/lib/utils/data-util`).with({
  DataStore: { }
});

rewiremock.enable();
const runUnderTest = require('/path/run.js')
rewiremock.disable();

Appears like there's a flaw in my understanding and approach. So I see the following error

Error: Cannot find module '/path/to/current/working/dir/lib/utils/data-util'
Full Stack Trace
 at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
      at Function.Module._load (internal/modules/cjs/loader.js:562:25)
      at Module.require (internal/modules/cjs/loader.js:692:17)
      at require (internal/modules/cjs/helpers.js:25:18)
      at Object. (/Users/saifas/Freshworks/DeveloperRelations/DeveloperTools/freshapps_sdk/lib/routes/app.js:5:19)
      at Module._compile (internal/modules/cjs/loader.js:778:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
      at Module.load (internal/modules/cjs/loader.js:653:32)
      at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
      at Function.Module._load (internal/modules/cjs/loader.js:585:3)
      at Module.require (internal/modules/cjs/loader.js:692:17)
      at require (internal/modules/cjs/helpers.js:25:18)
      at Object. (/Users/saifas/Freshworks/DeveloperRelations/DeveloperTools/freshapps_sdk/_test/helpers/run.help.js:15:19)
      at Module._compile (internal/modules/cjs/loader.js:778:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
      at Module.load (internal/modules/cjs/loader.js:653:32)
      at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
      at Function.Module._load (internal/modules/cjs/loader.js:585:3)
      at Module.require (internal/modules/cjs/loader.js:692:17)
      at require (internal/modules/cjs/helpers.js:25:18)
      at Context. (run.test.js:12:5)

Catch is that the module at ${global.PATH}/lib/utils/data-util doesn't even exist in the first place in order to require and mock. In reality this module exists on 3rd party developer's system which is actually required then.

I broadly understood, it resolves and then mocks all the dependencies (node, npm)

In the above case, it appears like I don't give anything to be resolved in the first place.

theKashey commented 3 years ago

This is the second time such issue appear (see #46) and it's expected to work. But it will be not try to "resolve" a file name at all. (consider it as a bug) So in order to mock a "virtual file" you'll need to mocks it in a way you will load it.

We know what node wants - Error: Cannot find module '/path/to/current/working/dir/lib/utils/data-util' Let's try to double check what rewiremock does

rewiremock(`${global.PATH}/lib/utils/data-util`).with({
  DataStore: { }
})
.toBeUsed(); // 👈

rewiremock.enable();
rewiremock.disable(); // 👈

⬇️ XXX was set to be used, but was unused

Saif-Shines commented 3 years ago

It appears like rewiremock doesn't print anything close to,

XXX was set to be used, but was unused

It might have been used indeed by rewiremock.

I still see the same error,

Error: Cannot find module '/path/to/current/working/dir/lib/utils/data-util'

Following is how my run.test.js appears like

const rewiremock = require('rewiremock').default;

describe('Micky Mouse', function(){
global.PATH = process.cwd();

it('disney world', function(){
// Around ~15 rewiremock'd modules
 rewiremock(`${global.PATH}/lib/utils/data-util`)
      .with({
        DataStore: {}
      })
      .toBeUsed();
    rewiremock.enable();
    const run = require('../../lib/cli/run');
    rewiremock.disable();
})

 after(function () {
    rewiremock.disable();
  });

})

Mentioned some code surrounding it, just incase bug lives outside our current focus.

I simply ran by

mocha run.test.js
theKashey commented 3 years ago

There is no const run = require('../../lib/cli/run'); in my case. It was just enable and just disable.

Alex0007 commented 1 year ago

@theKashey i can confirm that mocking of non-existent modules is not working (Node.js)

rewiremock('puppeteer').by('../versions/puppeteer-15/node_modules/puppeteer-15');
Error: Cannot find module 'puppeteer'
Require stack:
- /Users/alex/Development/projects/test-project/build/rewiremock.js

Putting placeholder empty package to node_modules resolves problem, but still unexpected behaviour