thlorenz/proxyquire

`createRequire` support & a way to access the mocked `require`

Opened this issue · 6 comments

The package I want to mock uses createRequire to require, which proxyquire doesn't proxy yet. To workaround, I tried:

proxyquire('./example', {
  module: {
    createRequire: (filename) => Object.assign((id) => require(id), {
      // ...some other stuff like `resolve`
    }),
    '@global': true,
  },
  // ... stubs I use
});

But then I found the require above can't be the mocked one. I wonder if you can support createRequire and give us a way to access the mocked require (so that we can mock createRequire to return a require with our own properties).

Thanks!

If it involves changing the API, probably not. But if you can find a way to make resolving work without API changes, PR welcome. Stubs would still be relative to the module under test or perhaps you'd resolve absolute paths.

it'd be gross, but eval('require') would work :-p

Ok I think I get it, I think you want your replacement for module to respect the stubs passed to proxyquire in the same call. It's reasonable for proxyquire to expose a mocked require for that but getting it in scope is tricky. Without changing the API for existing users, maybe the stubs arg could also be a function that returns a stubs object. That function could receive a value that would expose the mocked require.

That seems easy, nonbreaking, and in line with a number of userland APIs - as long as nobody was using the stubs object for a module that exports a function.

The stubs object I'm referring to is the map of module paths to module override values. So you can still override a module that exports a function.

So:

proxyquire('./foo', () => {module: {}})

That function would in reality receive an argument that exposes a require function which you could then use to in your mock module.

Sounds great - maybe it could be sent an object, that for now only contains require, so it can be extended later?