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
[Feature]: Add support for 'using' keyword to dispose mocks/spiesΒ #14294
Add support for the 'using' keyword, recently introduced in TypeScript 5.2, to handle the disposal of mock resources in Jest. This keyword provides a simple and efficient way to manage resources, and it could greatly enhance the cleanup process of mocks after each test run.
The 'using' keyword in TypeScript 5.2 is designed to automatically dispose of anything with a Symbol.dispose function when it leaves scope. Given its utility in managing resources such as file handles and database connections, applying this feature to Jest's mock resources would provide a cleaner and more efficient way to ensure that mocks are properly cleaned up after each test run. This could reduce the risk of memory leaks or other unexpected behavior, enhancing the reliability and performance of tests.
Example
These are just some examples that I would imagine I will use if it will be natively supported from the returned value of "spyOn" or "mock"
describe('...',()=>{it('...',()=>{
using spy=jest.spyOn(axios,'get')})})
{jest.mock('axios')
using axios=require('axios')describe('...',()=>{it('...',()=>{// ...})})}
{
using mocked=jest.mock('axios')describe('...',()=>{it('...',()=>{// ...})})}
Pitch
This feature aligns with the latest practices in TypeScript (and soon JavaScript), providing a more modern and efficient way to manage and dispose of mock resources. Given that Jest is a core tool for testing in the JavaScript ecosystem, it's crucial that it continues to evolve and incorporate these advancements. This feature would not just be a nice-to-have, but rather a significant improvement to Jest's handling of mock resources, making it a valuable addition to the core platform.
Reacted by barakyosi, Matan, Igor Goldny, Tobias Weibel, Kosta, Brendan Drew, Michael Solomon, Travis Stauffer, Noah Balsmeyer, Magamed Esmurziev and 5 more
Reacted by Igor Goldny and Stas (Stanislav) Korzovsky
changed the title [-][Feature]: Add support for 'using' keyword to dispose of mocks/spioes[/-][+][Feature]: Add support for 'using' keyword to dispose of mocks/spies[/+]on Jul 2, 2023
changed the title [-][Feature]: Add support for 'using' keyword to dispose of mocks/spies[/-][+][Feature]: Add support for 'using' keyword to dispose mocks/spies[/+]on Jul 6, 2023
Thanks. I think it is worth to think if Symbol.dispose could be added to Mock Function which is the return value of both jest.spyOn() and jest.fn().
But I canβt see it working with the Jest Object which is the return value of jest.mock(). For instance, fake timers are part of the object. Should they be reset too? Thatβs tricky, because faking time is global operation. If Symbol.dispose on the Jest object resets the state of mocks and fake timers, very soon this can get messy.
(I talk about fake timers, because node:test added Symbol.dispose support for their timers recently. Reference nodejs/node#48549.)
In the using axios = require('axios') example the returned object could have Symbol.dispose method already. So if the loaded object will have Symbol.dispose method, it will work without any involvement from Jest side. Would be good not to break that and thatβs it.
Probably it could work with jest.spyOn():
{
using spiedMethod=jest.spyOn(someObj,'someMethod')// do something// calls `spiedMethod.mockRestore()`}
Not sure if that makes sense with jest.fn(). One can use const and will be simply garbage collected. Or did I miss something? Canβt see why there would be a need to restore it explicitly (well.. to be precise, Jest is restoring all mock functions after running each test file already).
In general it sounds useful. At this moment the concrete use cases are somewhat undefined. I understand it isn't easy to reason about the limitations without digging into the internals of Jest. If you feel like getting your hands dirty, just try putting together a PR.
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.
Activity
[-][Feature]: Add support for 'using' keyword to dispose of mocks/spioes[/-][+][Feature]: Add support for 'using' keyword to dispose of mocks/spies[/+]mrazauskas commentedon Jul 5, 2023
Could you elaborate on what you would expect from
Symbol.disposeproperty in each of these cases? What should happen at the end of a block?SimenB commentedon Jul 5, 2023
Something like this is super exciting, but I also don't know if we can really attach semantics here without breaking somebody's workflow
[-][Feature]: Add support for 'using' keyword to dispose of mocks/spies[/-][+][Feature]: Add support for 'using' keyword to dispose mocks/spies[/+]tzachbon commentedon Jul 6, 2023
I would expect a full clean-up since the variable will be available only for the block:
1#
I assume it is also relevant for
jest.fn()2#, 3#
Restore the request to the original module.
Why would it break? By using
usingyou are expecting a dispose.It won't change the behavior of
var,constorlet.mrazauskas commentedon Jul 6, 2023
Thanks. I think it is worth to think if
Symbol.disposecould be added to Mock Function which is the return value of bothjest.spyOn()andjest.fn().But I canβt see it working with the Jest Object which is the return value of
jest.mock(). For instance, fake timers are part of the object. Should they be reset too? Thatβs tricky, because faking time is global operation. IfSymbol.disposeon the Jest object resets the state of mocks and fake timers, very soon this can get messy.(I talk about fake timers, because
node:testaddedSymbol.disposesupport for their timers recently. Reference nodejs/node#48549.)In the
using axios = require('axios')example the returned object could haveSymbol.disposemethod already. So if the loaded object will haveSymbol.disposemethod, it will work without any involvement from Jest side. Would be good not to break that and thatβs it.Probably it could work with
jest.spyOn():Not sure if that makes sense with
jest.fn(). One can useconstand will be simply garbage collected. Or did I miss something? Canβt see why there would be a need to restore it explicitly (well.. to be precise, Jest is restoring all mock functions after running each test file already).github-actions commentedon Aug 5, 2023
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.
tzachbon commentedon Aug 8, 2023
@mrazauskas @SimenB - Just making sure, is this something you plan to adopt? Should I consider contributing to this :)
mrazauskas commentedon Aug 8, 2023
What is
thisin the sentence above?In general it sounds useful. At this moment the concrete use cases are somewhat
undefined. I understand it isn't easy to reason about the limitations without digging into the internals of Jest. If you feel like getting your hands dirty, just try putting together a PR.github-actions commentedon Sep 7, 2023
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 30 days.
SimenB commentedon Sep 7, 2023
PR welcome, yeah π
SimenB commentedon Sep 8, 2023
Example in the wild: apollographql/apollo-client#11177
SimenB commentedon Dec 28, 2023
@tzachbon are you still up for sending a PR here? π
SimenB commentedon Feb 20, 2024
https://github.com/jestjs/jest/releases/tag/v30.0.0-alpha.3
github-actions commentedon Mar 23, 2024
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.