-
Notifications
You must be signed in to change notification settings - Fork 31
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
question: nodejs plugin and esm #80
Comments
A file could be mocked only if it was not required before. Then it could be replaced on This operation is very slow, you have to traverse ALL files and determine - should you wipe them from a cache, or not. Other libraries are wiping all the cache, but that's even slower, and leads to many issues with singletons. Long story short - but in your case, it's able to understand which file should be wiped. So it's not wiped, and, as a result, not replaced. Why it working in a first run - algorithms to determine which file should be wiped, and which should be replaced are different. It's easy to understand which to replace - you have a "parent" and name, relative to a parent, is easy to handle. During cache wipe it's the only name, so... shit happens. Name resolution is hard stuff, and even if rewiremock was created to solve it, it did not, and I recon - should not. It's not the fight we might win. How to fix
import { addPlugin, plugins } from 'rewiremock';
addPlugin(plugins.usedByDefault);
const module = rewiremock.proxy( () => require('./path/to/module'), () => {
rewiremock(() => require('/path/to/otherModule').with({});
}); In this case it's impossible to make a mistake - name resolution is handled by nodejs itself, and you will also maintain type information, if you have one.
forceCacheClear(false) // normal cache clearing, default
forceCacheClear(true) // aggressive cache clearing. Will restore module system like it was before, like you never execute any module via rewiremock
PS: You dont have to use |
thanks for your help and an explanation! |
Looks like |
I think I'm dumb and should just be able to stub it with Sinon |
deleted a question above, as I did in fact not need rewiremock at all for what I was doing. |
It's worth mentioning that I didn't end up needing |
Sinon itself a recommendation not to use sinon for dependency mocking, but its not quite clear. Take a look at this PR. |
hm. OK, so I’m unsure why rewiremock doesn’t work with I can try to come up with a more complete example (the one I deleted was a bit contrived). regarding the PR, I’m reading through more of it and your linked articles (and a video linked from the articles), but why I shouldn’t just stub |
Check - avajs/ava#665 and avajs/ava#1359 Never modify globals. That's something from the testing basics - you shall test I've tried to explain something about it here - https://dev.to/thekashey/please-stop-playing-with-proxyquire-11j4 |
This is a good point, and one I often never take into consideration given I know the implementation details of my testing framework. In other words, I know what Mocha touches and what it doesn't-- That talk you linked (from searls) is very informative. Given I'm finding mocking this particular bit of my code to be difficult, I'm going to take another pass at the code's structure. Likewise, I'm going to stop using |
In the same time |
sorry to bother again. I've been trying to figure out how to get around this for the past two workdays, and have been trying to follow your suggestions. I have a test which uses subject = rewiremock.proxy(
() => require('../A'),
() => {
rewiremock(() => require('../B'))
.with({foo: 'bar'})
}
); But I also have a test which I want to run against subject = rewiremock.proxy(
() => require('../B'),
() => {
rewiremock(() => require('../C'))
.with({bar: 'baz'})
}
); Running these tests together (not individually), the If I disable the An initial call in my harness code to import rewiremock, {addPlugin, overrideEntryPoint, plugins} from 'rewiremock';
import sinon from 'sinon';
// see https://github.com/unexpectedjs/unexpected/issues/631
const expect = require('unexpected');
global.sinon = sinon;
global.expect = expect
.clone()
.use(require('unexpected-sinon'))
.use(require('./unexpected-rxjs'));
overrideEntryPoint(module);
addPlugin(plugins.usedByDefault);
rewiremock.forceCacheClear(true); // or anything else
global.rewiremock = rewiremock; (I prefer having stuff like this in global scope for convenience; if rewiremock is incompatible with this sort of use, please advise!) |
(to be clear, that first test against A runs before the test against B) |
It seems that tests are not properly isolated from each other. Let me try to create a test for it. |
The tests is passing. Something else is not working as expected. Possible problem - one of the files is already mocked, and nested mocks are poisoning module (stored in a "scope") settings. Theoretically it's possible. If you have a |
Thanks, I’ll use your test to try to reproduce |
example distilling problem found in #80
Hi,
I was having some trouble using the
nodejs
plugin and relative paths with esm andrewiremock.module()
. I'm unable to provide a minimal case to reproduce the problem I'm having, but I'll try to explain:lib/foo.js
is a modulelib/baz.js
is another modulelib/bar/quux.js
is yet another modulelib/bar/quux.js
depends onlib/foo.js
lib/foo.js
depends onlib/baz.js
test/bar/quux.spec.js
is a test forlib/bar/quux.js
, which uses rewiremock to stublib/foo.js
test/foo.spec.js
is a test forlib/foo.js
, which uses rewiremock to stublib/baz.js
This is how I'm using rewiremock:
overrideEntryPoint()
in a separate test helper file to load rewiremockmocha -r esm
, and with thenodejs
plugin enabled.rewiremock.module(() => import('/path/to/module')
syntax.If I run each of those two tests individually, they both pass. If I run them together,
test/bar/quux.spec.js
runs first, thentest/foo.spec.js
runs. The latter fails, as it can't findlib/baz.js
, which is stubbed via the relative path../lib/baz
.In the resulting stack trace,
test/bar/quux.spec.js
appears at the top. Running the debugger, whentest/foo.spec.js
is trying to stub../lib/baz
, the "parent" module istest/bar/quux.spec.js
, which seems incorrect.A couple things I've noticed:
nodejs
plugin and use paths relative to the files under test (e.g.,lib/foo.js
stubs./baz
instead of../lib/baz
), all tests pass together (in other words, I'm not blocking on a fix)rewiremock.enable()
paired withrewiremock.disable()
seems to have no effect whatsoeverSo my question is if I should be using the
nodejs
plugin, or a different plugin, and how can I specify relative-to-test-file module paths to be stubbed? Is there a bug here?Thanks for your work on this module!
The text was updated successfully, but these errors were encountered: