Modifying globals within module leaks to global with Node >=10
See original GitHub issueWhen running the test suite with Node 10 or higher, the test should not influence other modules when injecting mocks
in the shared test cases fails. This happens because __set__
ing a global in moduleA.js
doesnβt set that global only within that module, but globally (so also in moduleB.js
and in the test suite itself). This should not happen, since it leaks to other tests and can have various unwanted effects. It did not happen with Node 9 (which is why Travis also didnβt pick this up - it tests with Node 6, 8 and 9), and I do not know why this happens using higher versions (Node 10, 11 and 12 all have this behaviour, starting from the very first v10.0.0).
What makes this case even more mysterious, is that since that test (should not influence ...
) sets console
to a dummy mock { }
(which should only have effect in moduleA
, but because of this bug also changes the global console
), all further Mocha output (which uses console.log
) is suppressed. It took me a while therefore, to actually notice this test was failing!
All other tests seem to pass fine β it.skip
the failing test, and you see the other tests pass:
63 passing (1s)
1 pending
This is also the easiest way to check that Mocha actually ran the other tests.
How to reproduce
I use nvm
to switch between node versions. (I left out some of the test results, as marked by ...
)
$ nvm use 9
Now using node v9.11.2 (npm v5.6.0)
$ npm test
> rewire@4.0.1 test /Users/Rens/Dev/rewire
> mocha -R spec
__get__
β should return the initial value
...
...
rewire
β should work like require() (101ms)
β should return a fresh instance of the module
β should not cache the rewired module
β should modify the module so it provides the __set__ - function (45ms)
β should modify the module so it provides the __get__ - function (57ms)
β should modify the module so it provides the __with__ - function (55ms)
β should provide __get__ as a non-enumerable property
β should provide __get__ as a writable property
β should provide __set__ as a non-enumerable property
β should provide __set__ as a writable property
β should provide __with__ as a non-enumerable property
β should provide __with__ as a writable property
β should not influence other modules
β should not override/influence global objects by default
β should provide a working __set__ method
β should provide a working __get__ method
β should provide a working __with__ method
β should provide the ability to inject mocks
β should not influence other modules when injecting mocks
β should provide the ability to mock global objects just within the module (41ms)
β should be possible to mock global objects that are added on runtime
β should not be a problem to have a comment on file end
β should not be a problem to have a module that exports a boolean
β should not be a problem to have a module that exports null
β should not be a problem to have a module that exports a sealed object
β should not be a problem to have a module that uses object spread operator
β should not be a problem to have a module that uses object rest operator
β should not influence the original require if nothing has been required within the rewired module
β subsequent calls of rewire should always return a new instance (46ms)
β should preserve the strict mode
β should not modify line numbers in stack traces
β should be possible to set implicit globals
β should throw a TypeError if the path is not a string
β should also revert nested changes (with dot notation)
β should be possible to mock undefined, implicit globals
β should be possible to mock and revert JSON.parse (see #40)
β should be possible to set a const variable
β should fail with a helpful TypeError when const is re-assigned
β should also work with CoffeeScript (43ms)
64 passing (1s)
$ nvm use 10
Now using node v10.16.0 (npm v6.9.0)
$ npm test
> rewire@4.0.1 test /Users/Rens/Dev/rewire
> mocha -R spec
__get__
β should return the initial value
...
...
rewire
β should work like require() (86ms)
β should return a fresh instance of the module
β should not cache the rewired module
β should modify the module so it provides the __set__ - function (54ms)
β should modify the module so it provides the __get__ - function (49ms)
β should modify the module so it provides the __with__ - function (45ms)
β should provide __get__ as a non-enumerable property
β should provide __get__ as a writable property
β should provide __set__ as a non-enumerable property
β should provide __set__ as a writable property
β should provide __with__ as a non-enumerable property
β should provide __with__ as a writable property
β should not influence other modules
β should not override/influence global objects by default
β should provide a working __set__ method
β should provide a working __get__ method
β should provide a working __with__ method
β should provide the ability to inject mocks
β should not influence other modules when injecting mocks
Note that the last 20-or-so tests disappeared, and there was no test result βx passing
β.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:13 (10 by maintainers)
Top GitHub Comments
So,
process
is still global, it is only not part of the enumerable keys ofglobal
. You can check this withwhich should return an integer (for me, it is 60) indicating it is in that list.
But indeed, the same bug is the cause of your problems. I have a fork that fixes it. I also submitted it as a PR, but it has been a long time since the last PR in this repo was merged.
Note, though, that the workaround to
__set__
process.exit
directly is strongly discouraged. Are you sure you are not simply modifying the globalprocess
?Published as v6.0.0 π