You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Sinon stubbing failed after upgrade to 3.9.2 #38568
Run the start.ts script by compiling it with tsc or simply use ts-node.
I'd expect it print fake stub but now it prints real stub. It's working as expected for typescript@3.8 or lower, start breaking from 3.9.2.
Expected behavior:
Print "fake stub"
Actual behavior:
Print "real stub"
Playground Link: Can't provide Playground link because it contains multiple files
The same problem exists for jasmine's spys. I tracked the problem down to this change #32264. After this change get and set properties of modules imported with star syntax are no longer enumerable which then causes a crash in jasmine's check here.
Most likely the same can be said for Sinon and I also saw a comment from someone having this problem with jest here.
Should we tell those libraries to adapt their code or can we have a flag to keep those properties enumerable?
Does your comment still apply if we are using "commonjs" modules, Ryan Cavanaugh (@RyanCavanaugh)? I noticed the following difference between the emitted modules:
Both modules work fine, but the latter (3.9) breaks our ability to mock the imported functions with Sinon. We've had to roll back to 3.8 until we can resolve.
If you're targeting commonjs but writing ES module imports/exports, TS is still going to try to give you ES module behavior.
This code is effectively not legal ES, since it's attempting to modify (indirectly via sinon.stub) a readonly property (the properties of something imported with import * as name are not mutable). It should never have worked.
Andreas (@AndyOGo) see jasmine/jasmine#1817 (comment) for an easy workaround monkey-patching tslib. I'm using this hack across 40 packages (Node.js and browser), works perfectly. This should work with any testing library supporting import mocking.
I noticed this only breaks if there is an export x from y in between your test code and the module you want to stub. If the module/function you want to stub is directly exported already, you can directly import it in your test code and this still works. Ended up saving me some refactoring and going down the proxyquire rabbit hole.
// file: ./src/stubber/index.ts
export { toStub } from './to-stub'
// file: ./src/stubber/to-stub.ts
export function toStub() {
console.log('real stub')
}
// file: ./src/start.ts
import * as sinon from 'sinon'
import * as stubber from './stubber'
import * as toStub from './stubber/to-stub'
(async () => {
// breaks: logs 'real stub' because toStub is an intermediate reference here
// (imported via the 'export from' in 'stubber/index')
sinon.stub(stubber, 'toStub').callsFake(() => {
console.log('fake stub')
})
stubber.toStub()
// works: because toStub is a direct reference
// (imported via 'export function' in 'stubber/to-stub')
sinon.stub(toStub, 'toStub').callsFake(() => {
console.log('fake stub')
})
toStub.toStub()
})()
If you're targeting commonjs but writing ES module imports/exports, TS is still going to try to give you ES module behavior.
This code is effectively not legal ES, since it's attempting to modify (indirectly via sinon.stub) a readonly property (the properties of something imported with import * as name are not mutable). It should never have worked.
Hi Ryan Cavanaugh (@RyanCavanaugh) so if we are targeting 'commonjs', how can be writing without ES module imports/exports in ts 3.9? I mean how can we make it mutable? Thanks.
i mean "module": "commonjs",
"target": "es2017",
Activity
nico1510 commentedon May 14, 2020
The same problem exists for jasmine's
spys. I tracked the problem down to this change #32264. After this changegetandsetproperties of modules imported with star syntax are no longer enumerable which then causes a crash in jasmine's check here.Most likely the same can be said for Sinon and I also saw a comment from someone having this problem with jest here.
Should we tell those libraries to adapt their code or can we have a flag to keep those properties enumerable?
msholty-fd commentedon May 14, 2020
I found this code to break when upgrading from 3.8.2 to 3.9.2. We use
ts-jestto transform our TypeScript Jest tests.I would get an error like:
I resolved this by doing this workaround:
It's not pretty, but it at least unblocked me from upgrading.
RyanCavanaugh commentedon May 14, 2020
ES module exports are specified to not be enumerable, so this is the expected behavior. Prior behavior was out of compliance with the spec.
mdurling commentedon May 14, 2020
Does your comment still apply if we are using
"commonjs"modules, Ryan Cavanaugh (@RyanCavanaugh)? I noticed the following difference between the emitted modules:Before
After
Both modules work fine, but the latter (3.9) breaks our ability to mock the imported functions with
Sinon. We've had to roll back to 3.8 until we can resolve.RyanCavanaugh commentedon May 14, 2020
If you're targeting
commonjsbut writing ES module imports/exports, TS is still going to try to give you ES module behavior.This code is effectively not legal ES, since it's attempting to modify (indirectly via
sinon.stub) a readonly property (the properties of something imported withimport * as nameare not mutable). It should never have worked.typescript-bot commentedon May 18, 2020
This issue has been marked as 'External' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
squidfunk commentedon May 18, 2020
See jasmine/jasmine#1817 (comment) for a temporary workaround.
adjerbetian commentedon May 20, 2020
Ryan Cavanaugh (@RyanCavanaugh) Sorry, I didn't understand your answer when you said
I created a demo project here typescript-3.9-commonjs with a very simple node script.
Do you mean that I should write
index.tsdifferently?JordanPawlett commentedon Jun 3, 2020
Just the workaround i was looking for!
denieler commentedon Jun 19, 2020
Yeah, having the same issue, very annoying 👍
Fix App callCount test by no longer stubbing free-standing function g…
Export the users (getCurrentUser) method as part of an object so that…
Export api course functions in an object due to TypeScript update
10 remaining items
Replace API standalone functions due to TypeScript update
Fix App callCount test by no longer stubbing free-standing function g…
Export the users (getCurrentUser) method as part of an object so that…
Export api course functions in an object due to TypeScript update
Free standing functions cannot be stubbed
Import FacultyAPI object instead of free-standing function getFaculty…
Replace API standalone functions due to TypeScript update
Stand-alone functions cannot be stubbed - MultiYearPlanAPI was added
Create MetadataAPI interface
AndyOGo commentedon May 17, 2021
Ryan Cavanaugh (@RyanCavanaugh)
You are right, ES module exports shall not be enumerable.
Though may I ask you to consider testability.
And please do not publish breaking changes as a patch.
squidfunk commentedon May 17, 2021
Andreas (@AndyOGo) see jasmine/jasmine#1817 (comment) for an easy workaround monkey-patching
tslib. I'm using this hack across 40 packages (Node.js and browser), works perfectly. This should work with any testing library supporting import mocking.AndyOGo commentedon May 17, 2021
Related:
microsoft/tslib#103
FauxFaux commentedon May 17, 2021
I did a similar thing with babel, https://github.com/snyk/babel-plugin-mutable-imports , but ended up just forking sinon to make it warn, and fixing all the code. sinonjs/sinon#2319
shawnjones253 commentedon Jun 9, 2022
I noticed this only breaks if there is an
export x from yin between your test code and the module you want to stub. If the module/function you want to stub is directly exported already, you can directly import it in your test code and this still works. Ended up saving me some refactoring and going down the proxyquire rabbit hole.cqcmdwym commentedon Sep 5, 2023
Hi Ryan Cavanaugh (@RyanCavanaugh) so if we are targeting 'commonjs', how can be writing without ES module imports/exports in ts 3.9? I mean how can we make it mutable? Thanks.
i mean "module": "commonjs",
"target": "es2017",