-
-
Notifications
You must be signed in to change notification settings - Fork 771
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
Document how to configure Node to allow stubbing EcmaScript modules #1832
Comments
I've been thinking about writing exactly this :) |
The "problem" is that there is a plethora of different ways |
Hi @fatso83! The |
I'd like to write unit test with the minimum cost. If the solution would be so tricky, I'd rather abandon the unit test with mock. After all, mock test is not the imperative method to build a robust online system. But, as a last resort, is it possible that sinon wraps the "proxyrequire" (or something like this) for me ? |
@jim-king-2000 That is out of scope. You have chosen explicitly to use a module system whose exports is supposed to be immutable. That is unfortunately a cost you'll have to bear on your own part. Wrapping module loaders, making them work in all kinds of scenarios (Node, browser, with/without transpilers, etc) is too costly and doesn't really have anything to do with this project's stated goals. |
I don't quite understand the relevance of sinon and module system (I'm sorry). What I need is a js/node mock unit test framework (or library, like the java counterpart, mockito) without babel. So, does it exist? |
In short, for your specific niche: not currently 😭 In Java terms, it's like implementing your entire system using Java That being said, all you need to make things work is rename your |
For the Java's static function mocking, we use powermock. But I may not fully understand the comparison. By the way, I don't like java, it's evolution is too slow. Now it still does NOT support async/await. I use *.mjs everywhere, all of the source codes are mjs files. Further more, it means that I have to resort to babel again (introducing extra dev/run-time work and messy call stack). It is OK if I could only change the test files back to *.js. I'm going to abandon ut with mock (other tests are intact) until I find some other low-cost ways. |
@fatso83 Thank you for the help all along. |
Does anyone tried quibble? 🤔 |
FYI, I implemented Node.js ESM support in "testdouble.js", which is a mocking library. It is possible. I wrote about the implementation in this blog post: Would be glad to assist here if anybody wants to take it on.. |
@giltayar Congratulations on implementing the ESM support! Great article, btw. We have always said that ES Module stubbing is not possible in conforming ESM Runtimes, but we have also said (like above) that this should be handled at the linking level, using something like proxyquire, rewire, or ... Quibble, which is where you added the support :) In my work project we have used proxyquire('./mylib.mjs', {doSomething: () => 'done'}) It would be quite equivalent in Quibble (used by TestDouble), where the article has an example like this, but Quibble does not support partial stubs, so it's a bit different in what they do. await quibble.esm('./mylib.mjs', {doSomething: () => 'done'}, 'yabadabadoing') // not sure what this third param does ... So in keeping with what has been said earlier, Sinon will never explicitly add support for mocking ES Modules, as that is better left to Quibble, Proxyquire, Rewire, NormalModuleReplacementPlugin (webpack) and all the other ways of doing this that is 100% environment dependent. |
@fatso83 If I may ask why this is such a convinced "never explicitly add support"? I read that multiple times here in the last days while desperately searching for a solution to mock my ES6 module code. No solutions documented at Jest, none are here. I almost gave up until I found the article of @giltayar. Such a relief. I got something working with quibble until I realized that I can just use testdouble.js. It is already difficult enough that in JavaScript every package has its own documentation style and most of the time no real API docs, but also having to figure out how test libraries work, mocking libraries work and module loaders for mocking libraries work is just too much. I totally agree if you say that you focus on Sinon as it is while others can focus on wiring those packages together for the "end user" programmer. I only want to show, that there is real pain for programmers like me and I am sure that many would be happy if the process gets simplified, especially if many will move to ES modules in the next years. I do not have such a deep technical understanding, I just thought some feedback of my experience could be helpful |
Let me re-iterate: it is the opinion of the Sinon maintainers that dealing with mocking imports is out of scope for Sinon and is better tackled by specialised libraries. Generally, it doesn't make sense to make a library that tries to do everything, in every single runtime. Not even bigger, well funded open source projects try to do this.
Different libraries make different choices. The maintainers of testdouble.js make their own choices. They decided to publish quibble and integrate it into their library. Good for them. If you like their solution, then by all means use it. We have nothing but love and respect for @searls and the maintainers of testdouble.js.
We are not here to solve every single problem in the JavaScript eco-system. For more than a decade, various maintainers have provided the Sinon family of libraries for free. Practically all of the work that has gone into maintaining these libraries have been done as unpaid work, in the free time of the maintainers. We are using JavaScript ourselves professionally and share your frustrations. But, we only have so much time to give away for free.
What would be helpful would be if you wrote a blog post about your frustrations mocking dependencies, until you came upon a solution that worked well for you, and how you've used testdouble.js to great success with your particular way of loading JavaScript. If it turns out to be a solid blog post, I'd be happy to promote it on |
@mroderick I guess I should have first make clear that you and the Sinon maintainers have my upmost respect!
Definitely not, that was just meant to show that there might be a bigger need for help than with other languages (just my guess).
Fair enough, as I said, I can understand that and probably you have a way deeper understanding of the effort that is involved by implementing those features. Also the loader API is still experimental. I am currently working on a small CLI tool that I plan to release as open source as soon as there is a working version. If that is done I consider to write a blog post about it. I will still try Sinon with |
We have a guide on how to do that: https://sinonjs.org/how-to/link-seams-commonjs/ If you find that the guide can be improved, please send a pull request 👍 |
EcmaScript modules that run in an environment supporting them (meaning they haven't been transpiled using Babel to ES5) and export a
default
function of some kind cannot be stubbed, as ES namespaces are immutable per the spec. There is nothing Sinon can do about this, so we explicitly throw an error when you try to do this:'ES Modules cannot be stubbed'
.But @jdalton has made
esm
, a runtime loader for Node that enables loading EcmaScript modules (*.mjs
), and to allow stubbing using Sinon and the like, he has added themutableNamespace
option toesm
.There should be an article under our How to section that shows how one can set up
npm
to execute node usingesm
and the option, along with a test script.References:
The text was updated successfully, but these errors were encountered: