Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't require files with mocked filesystem #130

Closed
xavdid opened this issue Jun 28, 2016 · 13 comments
Closed

Can't require files with mocked filesystem #130

xavdid opened this issue Jun 28, 2016 · 13 comments

Comments

@xavdid
Copy link

xavdid commented Jun 28, 2016

Hey there!

So I'm having sort of a weird problem. I'm testing a function that reads from a file and does stuff with the contents. I'm using mock-fs and everything is great. However, one of the modules I'm using changed their code so that there are require statements in functions that get called during the test (in my case, an HTTP request). When the mock is active, require('./blah') fails because unless I've mirrored that file (which lives > 3 levels down in node_modules), it's not found. More specific examples are here.

Is it currently possible (or possible to add) an option so that the fs is mocked as normal, but all calls to require are untouched?

@tschaub
Copy link
Owner

tschaub commented Jun 30, 2016

I agree that it would be nice if require would still use the real filesystem in this case. If anybody comes across this and is interested in digging to see if there would be a reliable way to make this work, I'd welcome suggestions. I won't have time for it in the near future, but will dig a bit when I get the chance.

@xavdid
Copy link
Author

xavdid commented Jul 5, 2016

I've been taking a look, but there's a lot of code and I'm not sure I know enough js at this point to make a dent. In any case, here's my (truncated) stacktrace:

    Error: ENOENT, no such file or directory '/Users/david/projects/heroku-config/node_modules'
      at Binding.<anonymous> (node_modules/mock-fs/lib/binding.js:866:13)
      at maybeCallback (node_modules/mock-fs/lib/binding.js:41:17)
      at Binding.lstat (node_modules/mock-fs/lib/binding.js:863:10)
      at Object.fs.lstatSync (node_modules/mock-fs/node/fs-6.0.0.js:887:18)
      at Object.realpathSync (node_modules/mock-fs/node/fs-6.0.0.js:1522:21)
      at require (internal/module.js:20:19)
      at Heroku.request (node_modules/heroku-client/index.js:9:19)

the line that's calling it can be found here

I'm not sure that there's access to the actual fs while in the fs-6.0.0 file, so it's hard to say if it's possible at all.

@tschaub
Copy link
Owner

tschaub commented Jul 8, 2016

@xavdid if you are able to give the change in #139 a try, I'd appreciate feedback on whether that works for your case.

I think this is good default behavior. Because it would break cases where people actually wanted to require() mocked files, this would need to be a major version bump.

@xavdid
Copy link
Author

xavdid commented Jul 8, 2016

Awesome, this works like a charm!

As for the major version bump, we could get around it by adding realRequire or similar as an option, assuming the options object is available when building the new bindings.

Hopefully there's some way to conditionally include the old behavior (though I think your patch is the better default). I'd even be happy with the new behavior locked behind an option as long as it's reachable.

@tschaub
Copy link
Owner

tschaub commented Jul 9, 2016

Ok, I dug a bit further into this. I think the current behavior around require() is buggy at best and the change in #139 should be considered a bug fix. As it is currently, after setting up a mock filesystem, you can only require() mock files that also exist in the real filesystem. This is because Node's module.js uses functions from both the fs module (which are mocked) and functions from the fs binding (which are not mocked for the module.js module, only the fs.js module).

So I'm going to publish the changes in #139 as part of a minor release.

@timkendrick
Copy link
Contributor

Is there any way you can require() files from the mock filesystem then?

Context: I'm trying to write tests for a library that internally uses require() to load a webpack configuration from a user-provided webpack.config.js file. I'd like to be able to test this with a variety of mock config files – is this possible using mock-fs, or do I have to create these files in the real filesystem? Thanks!

@tschaub
Copy link
Owner

tschaub commented Jul 10, 2016

@timkendrick if you want to test the behavior of require(), others have suggested https://github.com/thlorenz/proxyquire.

This module is about providing an in-memory filesystem for the functions in the fs module. The require() function uses more than the functions in the fs module to load files.

@timkendrick
Copy link
Contributor

Thanks @tschaub, that sounds perfect!

@xavdid
Copy link
Author

xavdid commented Mar 2, 2017

Hey, just revisiting this. v4 looks like a great release, but it does reintroduce this issue (though that seems purposeful). I was curious about the context for the regression.

For me, I'm fine to lock into v3 for my tests, I was just wondering. Thanks for all your hard work!

@tedp
Copy link

tedp commented Mar 30, 2017

Having the same problem with versions after 3.11.0. Would be good to know why this fix was reverted.

@ghost
Copy link

ghost commented Sep 15, 2017

I'm having this issue too. Very annoying...

@amerryma
Copy link

Unfortunately I can't use v3 right now as I'm using node 8.6. Any updates on this?

@aaron-goshine
Copy link

Why do node developer keep reinventing the wheel.. there are more than a thousand packages that already have the functionality to mock required packages...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants