-
Notifications
You must be signed in to change notification settings - Fork 150
Something is wrong with a cache #805
Description
Derived from #798, #799 and theKashey/rewiremock#83
There is a simple test:
A.js<- reexports <-B.js<- reexports <-C.js- changing
C.js, would changeBandAresults, which are the same.
// A.js
import B from './B';
export default B;
// B.js
import C from './C';
export default C;
// C.js
export default 42;Test 1
const subject = rewiremock.proxy(
() => require('./A'),
() => {
rewiremock(() => require('./B')).with('bar')
}
);
expect(subject.default).to.be.equal('bar')In this test we are replacing B by "bar". It is working
Test 2
it('mock B', () => {
const subject = rewiremock.proxy(
() => require('./B'),
() => {rewiremock(() => require('./C')).withDefault('baz')}
);
expect(subject.default).to.be.equal('baz')
});This time test would fail. C would be not mocked, as long as B cache would be reused, so it never gets a change to get mocked - execution enters ESM loader with "B", and exists with a result, never calls Module._load again.
Test 3
Add one more test, between these two
it('mock C', () => {
const subject = rewiremock.proxy(
() => require('./A'),
() => {rewiremock(() => require('./C')).with('bar')}
);
expect(subject.default).to.be.equal('bar')
});It would fail, but test 2 which would be executed right after it, will pass.
Test 4
- Keep only
Test 2- green - Duplicate it - green
- Add
Test3- green - Add
Test1- the test afterTest1is red - replace
A.jsbymodule.exports = require('./B');- all tests are green.
So - there is something like cache poisoning, which take a place after A.js
Add D.js
I've extended chain by D.js, then started modifying the code.
- A->B(mock) - test ok, following fails
- A->B->C(mock) - test ok, following fails
- A->B->C->D(mock) - test ok, following ok. This is beyond my imagination.
- B->C would crash following A->D.
I've also tried to run rewiremocks tests vs esm and majority failed due to cache related issues.
I've also tried to disable ESM cache, but it has no effect.
Theory
Some parts of rewiremock uses require.cache, while others uses Module._cache. While it's the same for nodejs and webpack, it might not be the case for esm.