Skip to content
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

Doesn't work with ES6 consts #79

Closed
erbridge opened this issue Oct 14, 2015 · 28 comments
Closed

Doesn't work with ES6 consts #79

erbridge opened this issue Oct 14, 2015 · 28 comments

Comments

@erbridge
Copy link

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)
@erbridge erbridge changed the title Doesn't work with ES6 consts. Doesn't work with ES6 consts Oct 14, 2015
@brenolf
Copy link

brenolf commented Oct 15, 2015

+1 for this. My workaround was using let instead of const to enable it to rewire.

@erbridge
Copy link
Author

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...

@jhnns
Copy link
Owner

jhnns commented Nov 2, 2015

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.

@dcrockwell
Copy link

+1 for ES6 consts. Thanks to @brenolf for the workaround.

@alexweber
Copy link

@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.

@kaktus42
Copy link

I can't reproduce this issue.
I can rewire const functions.

@jhnns
Copy link
Owner

jhnns commented May 19, 2016

Do you have an example? I'm pretty sure that this can not work.

@kaktus42
Copy link

var r = rewire('./reducer');
const reduceAddAction = r.__get__('reduceAddAction');

Where reduceAddAction is a const function.

But maybe you were talking about overwriting?

@jhnns
Copy link
Owner

jhnns commented May 19, 2016

But maybe you were talking about overwriting?

Exactly

@awinder
Copy link

awinder commented Jun 9, 2016

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 😄

@jhnns
Copy link
Owner

jhnns commented Jun 10, 2016

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.

@daithi-coombes
Copy link

+1 for allowing rewire of const's

@kimpellikaan
Copy link

+1 again!

@rewiregps
Copy link

rewiregps commented Aug 20, 2016

you should check this out : https://mathiasbynens.be/notes/es6-const
+1 for rewire

@BadgerBadgerBadgerBadger

+1 yet again!

@ioanlucut
Copy link

+1

@shivarajnaidu
Copy link

shivarajnaidu commented Sep 29, 2016

+1 for const and for full es6 support...

@tbranyen
Copy link

@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.

@jhnns
Copy link
Owner

jhnns commented Oct 20, 2016

@shivarajnaidu I'm thinking about ES6 support, but it's not that easy :) – especially as long as the loader spec is not finished yet.

@jsrraman
Copy link

jsrraman commented Nov 24, 2016

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' };
    };

@jhnns
Copy link
Owner

jhnns commented Apr 9, 2018

Rewiring const is supported since 3.0.0

@jhnns jhnns closed this as completed Apr 9, 2018
@mririgoyen
Copy link

@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
Copy link
Owner

jhnns commented Apr 24, 2018

@goyney Your example should work. Could you provide a demo that makes it reproducible. I did found a bug though where const was not properly detected when it was written like: const{ apiRoot .... I published a fix with 4.0.1

@Sufiane
Copy link

Sufiane commented Jul 30, 2018

@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)

@pandomic
Copy link

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');

@andreisaikouski
Copy link

Still having this issue even with rewire 5.0.0, any fixes or workarounds?

@siva-natarajan
Copy link

Still having this issue even with rewire 6.0.0, any fixes or workarounds?

@ahmedfourati
Copy link

I just had to change es6 to es5 and it worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests