I've built a calendar around moment.js
and I'm working on unit tests right now.
The first problem I solved was how the date will change when the tests run, so I've been able to lock down the moment using this guidance.
Currently, I'm stuck on an error:
"TypeError: Cannot read property 'weekdaysShort' of undefined"
My code has a line: const dateHeaders = moment.weekdaysShort();
By implementing the mocked moment().format()
, I've essentially lost the rest of the library.
My immediate question is how I can set up jest to let me return the array that you get from moment.weekdaysShort();
My larger question is whether I've gone down the wrong path and should come up with another strategy.
Things I've tried with unsuccessful results
weekdayShort
function:const mockMoment = function() {
return {format: '2016–12–09T12:34:56+00:00'}
};
mockMoment['weekdaysShort'] = () => ['Sun', 'Mon', 'Tues']; // etc etc etc
jest.mock('moment', () => mockMoment);
__mocks__
folder. I didn't go too far down this path because it started to feel like I'd have to copy/paste the entire Moment.js library into the mock. And while it'd be cool to figure out how they do what they do, that's a project for another day.jest.spyOn
- doesn't work because I'm not spying on a module.At this point, I'm considering abandoning the Moment
function for an array passed in through props. And while I'm confident that'll get me past this problem, it feels like I'm gonna hit another roadblock quickly afterwards.
Thanks in advance for the help.
Spying on the function using jest.spyOn Another approach to mock a particular function from an imported module is to use the jest.spyOn function. The API for this function seems to be exactly what we need for our use case, as it accepts an entire module and the particular export that should be spied on.
There are three simple (and a bit confusing) steps of mocking only one function of a module and leaving the rest of it to its default implementation. Create a mock for the entire module. Tell that mock to use actual (non-mocked) implementations for everything. Mock the desired function of the mock. A bit of a tongue twister, isn’t it?
jest.requireActual (moduleName) Returns the actual module instead of a mock, bypassing all checks on whether the module should receive a mock implementation or not
This isn’t strictly a Jest testing guide, the same principles can be applied to any application/tests that need to mock CommonJS or ES Modules. CommonJS: Node.js’ built-in import system which uses calls to a global require ('module-y') function, packages on npm expose a CommonJS compatible entry file.
Just found out the pattern I commonly use was provided in a 2016 github thread and, in all honesty, that's probably where I found it even though I don't specifically remember it :)
jest.mock('moment', () =>
const original = jest.requireActual('moment');
return {
__esModule: true,
default: {
...original,
...just the parts you want to mock
}
}
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With