Doesn't work with ES6 consts
erbridge opened this issue ยท 28 comments
You get errors like this:
TypeError: Assignment to constant variable.
at eval (eval at __set__ (my-module.js:73:19), <anonymous>:1:21)
at Object.__set__ (my-module.js:73:5)
at Context.<anonymous> (my-module-test.js:131:55)
+1 for this. My workaround was using let
instead of const
to enable it to rewire.
Yes, that works, and is my current workaround, but I really don't want to have to open the code up to bugs in order to test it...
Well ... re-assigning const
is not possible, rewire can't change this.
In order to do this, rewire would need to change the code (like @brenolf did manually). Therefore, we would need to use a parser which is currently out of scope.
However, if we want to support ES6 modules someday, we will need a parser anyway, so I'll consider this when rewriting rewire.
+1 for ES6 consts. Thanks to @brenolf for the workaround.
@erbridge @brenolf dcrockwell @dcrockwell For what it's worth, proxyquire seems to work fine using ES6 consts.
I've yet to write some more complex tests with it but initial results are encouraging.
I can't reproduce this issue.
I can rewire const functions.
Do you have an example? I'm pretty sure that this can not work.
var r = rewire('./reducer');
const reduceAddAction = r.__get__('reduceAddAction');
Where reduceAddAction
is a const function.
But maybe you were talking about overwriting?
But maybe you were talking about overwriting?
Exactly
Riffing on what @kaktus42 was saying though, you can take advantage of the way JS const works for evil and profit in the case when it's an object:
var r = rewire('./reducer');
const reduceAddAction = r.__get__('reduceAddAction');
reduceAddAction.method.to.stub = sinon.stub();
In this case you're not reassigning the variable identifier, and you're changing a referenced value, so it is possible, whether or not it's a good idea or not is another thing entirely ๐
I think it's totally valid to change const
objects, because const
does not mean that the object itself is frozen (you could use Object.freeze()
for that ๐ ). However, I would not change the code just for the test framework.
+1 for allowing rewire of const's
+1 again!
you should check this out : https://mathiasbynens.be/notes/es6-const
+1 for rewire
+1 yet again!
+1
+1 for const and for full es6 support...
@rewiregps You link an article that very well articulates why this cannot work. The bindings are immutable. So this already works exactly how it should. You cannot override a const binding, which is what rewire does.
@shivarajnaidu I'm thinking about ES6 support, but it's not that easy :) โ especially as long as the loader spec is not finished yet.
Well, in my case, I needed to stub a method from a private const of a module. proxyquire supports this use case
For example
my-module.js
const http = require('http')
my-module-spec.js
const proxyquire = require('proxyquire');
const myModule = proxyquire('./my-module', { 'http': httpStub });
httpStub.Server = app => {
return { key: 'value' };
};
Rewiring const
is supported since 3.0.0
@jhnns 4.0.0 here, this does not work.
main.js
const { apiRoot, defaultPort } = require('config');
main.test.js
const myModule = rewire('myModule');
myModule.__set__('defaultPort', 123);
TypeError: Assignment to constant variable.
@jhnns I do have the same problem as @goyney :(
I already have rewire 4.0.1
The only difference I have is that it's not from destructuring.
Demo:
index.js:
const myPromisifiedFunction = promisify(someFunct.ToPromisify)
index.test.js:
const myModule = rewire('../myModule')
const myStub = sinon.stub()
const myStubbedFunction = myModule.__set__('myPromisifiedFunction', myStub)
And what I get when running tests is:
TypeError: Assignment to constant variable. at eval (eval at __set__ (index.js:159:5), <anonymous>:1:19) at Object.__set__ (index.js:159:5) at Object.<anonymous> (test/index.test.js:14:48)
As a possible "dirty" workaround, it's possible to __get__
the function you need to test (which you expect to call other funcs), convert it to string, eval and test it in the context of your test. It works for small functions, but I'm sure with larger ones it might be a bit painful.
// myfunc.js
const unmockable = (a) => `Hello ${a}`;
const myLovelyFunc = (a) => unmockable(a);
module.exports = { myLovelyFunc };
// - - - - - - - - - - - - - - - somewhere in myfunc.test.js - - - - - - - - - - - - - - -
const myLovelyFunc = rewire('./myfunc.js').__get__('myLovelyFunc');
const subject = eval(myLovelyFunc.toString());
// Redefining function's local context
const unmockable - jest.fn(`Bye, ${a}`);
subject('Dude'); //=> Bye, Dude
expect(unmockable).toHaveBeenCalledWith('Dude');
Still having this issue even with rewire 5.0.0
, any fixes or workarounds?
Still having this issue even with rewire 6.0.0, any fixes or workarounds?
I just had to change es6 to es5 and it worked.