tschaub / mock-fs

Configurable mock for the fs module
https://npmjs.org/package/mock-fs
Other
906 stars 86 forks source link

TypeError on import or require #344

Open JamieGoodson opened 2 years ago

JamieGoodson commented 2 years ago
import mock from 'mock-fs';
...

or

const mock = require('mock-fs');
...

Results in

TypeError: Cannot read properties of undefined (reading 'read')

Node: v17.0.1 TS: v10.2.1 mock-fs: 5.1.2

3cp commented 2 years ago

I got no issue with both Node v17.0.1 and v17.1.0 and mock-fs v5.1.2.

What's TS v10.2.1?

JamieGoodson commented 2 years ago

What's TS v10.2.1?

TypeScript 🙂

3cp commented 2 years ago

Current typescript is v4. What's v10?

blutorange commented 2 years ago

Got the same problem after updating... something.

I've tracked down the issue to getReadFileContextPrototype in readfilecontext.js.

It works with plain node, but it does not work with yarn PnP (3.1.1). When I run this code from the above mentioned file:

getReadFileContextPrototype = function() {
  const fs = require('fs');
  const fsBinding = process.binding('fs');

  const originalOpen = fsBinding.open;

  let proto;
  fsBinding.open = (_path, _flags, _mode, req) => {
    proto = Object.getPrototypeOf(req.context);
    return originalOpen.apply(fsBinding, [_path, _flags, _mode, req]);
  };

  fs.readFile('/ignored.txt', () => {});

  fsBinding.open = originalOpen;

  return proto;
}

With just node, it returns the prototype. With yarn node, it returns undefined. Happens with node 14 and 16.

Are other people with this issue also using yarn?

blutorange commented 2 years ago

Seems like when using yarn, it only works with mock-fs@5.0.0 and node 14:

Using mock-fs@5.0.0 with node 16 gives a different error, but it seems to be the same underlying cause.

webstackdev commented 2 years ago

Are other people with this issue also using yarn?

I'm having it after migrating to Yarn 3 + PnP

3cp commented 2 years ago

I assume yarn pnp monkey-patched nodejs internals (something like what mock-fs does). The other tool does this practice is jest, which mock-fs also has difficulty to work with.

tschirmer commented 8 months ago

I found that the getReadFileContextPrototype will alwasy return null if you first call:

jest.mock('fs');

in your test before mock.

within this function:

exports.getReadFileContextPrototype = function () {
  const fs = require('fs');
  const fsBinding  = process.binding('fs');

  const originalOpen = fsBinding.open;
  let proto;

  fsBinding.open = (_path, _flags, _mode, req) => {
    proto = Object.getPrototypeOf(req.context);
    return originalOpen.apply(fsBinding, [_path, _flags, _mode, req]);
  };;

  fs.readFile('/ignored.txt', (err) => {});

  fsBinding.open = originalOpen;

  return proto;
};

When all of the fs functions are mocked, and the fsBinding.open never gets called, so proto stays undefined.

https://stackoverflow.com/questions/70447223/const-mock-requiremock-fs-gives-typeerror-cannot-read-properties-of-und/77604547#77604547

tschirmer commented 8 months ago

This is happening to me using jest + typescript + mock-fs on es6 module mode. When I was using commonjs without typescript, it ran with the jest.mock('fs') just fine.

tschirmer commented 8 months ago

I've also found the following if anyone's interested: Using Typescript:

or a

Error: ENOENT: no such file or directory, open 'C:\Users\Tony\Dev\var\data\unit_test\test.json'

so I converted all of my readFileSync -> readFile and writeFileSync -> writeFile within my tests + code and they seemed to work.

I'm not sure why this is. I have my suspicion that there might be something funny when running everything with es6 modules + typescript. es6 module imports work asynchronously, where as commonjs require doesn't, so there might be something around that when loading the fsBinding.