Thanks for this article! You expressed almost all issue which I have faced with jest.mock too. I see a lot of codebase where all tests bases on jest.mock. And it is really hard to support and develop such projects. jest.mock makes tests 'unfair' because they grabs and instantiate dependencies implicitly during module loding. Instantiation during loding sometimes gives a lot of issues with unittesting. I saw unit test which requires real db connection to run unit-tests, for instance when need to mock model for mongoose, typegoose packages.
I see your approch very usefull when I need a quick refactoring for existed codebase. But all new code I prefer to write in OOP style (i.e. with classess) with dependencies which passed via constructor with help of IoC (like inversify package).
I will put your article in bookmars to show other devs. Because I thought that only I avoid using jest.mock.
I beleave that the third option (i.e. jest.spyOn) is not so good due to reasons you have described already (shared state between unit-tests and etc.). I would suggest to use spyOn in this way:
1) share this code with all tests: const { dependencies, execute } = buildAction({
createPerson: jest.fn()
});
2) in each tests, add its own spyOn: jest.spyOn(dependencies, "createPerson").mockImplementationOnce(() => {
throw new Domain.InvalidColourError();
});
(spyOn will be garbage collected after each tests due to the reference on dependencies will be out of scope, so we no need to call clearAllMocks)
(It should help to remove beforeAll/Each from the tests - because there have some ideas that this methos breaks single responsibility in unit tests (see XUnit Framework idea and docs.microsoft.com/en-us/dotnet/co...)
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Hi Keith
Thanks for this article! You expressed almost all issue which I have faced with
jest.mock
too. I see a lot of codebase where all tests bases on jest.mock. And it is really hard to support and develop such projects.jest.mock
makes tests 'unfair' because they grabs and instantiate dependencies implicitly during module loding. Instantiation during loding sometimes gives a lot of issues with unittesting. I saw unit test which requires real db connection to run unit-tests, for instance when need to mock model for mongoose, typegoose packages.I see your approch very usefull when I need a quick refactoring for existed codebase. But all new code I prefer to write in OOP style (i.e. with classess) with dependencies which passed via constructor with help of IoC (like
inversify
package).I will put your article in bookmars to show other devs. Because I thought that only I avoid using
jest.mock
.I beleave that
the third option
(i.e. jest.spyOn) is not so good due to reasons you have described already (shared state between unit-tests and etc.). I would suggest to use spyOn in this way:1) share this code with all tests:
const { dependencies, execute } = buildAction({
createPerson: jest.fn()
});
2) in each tests, add its own spyOn:
jest.spyOn(dependencies, "createPerson").mockImplementationOnce(() => {
throw new Domain.InvalidColourError();
});
(spyOn will be garbage collected after each tests due to the reference on
dependencies
will be out of scope, so we no need to call clearAllMocks)(It should help to remove beforeAll/Each from the tests - because there have some ideas that this methos breaks single responsibility in unit tests (see
XUnit Framework
idea and docs.microsoft.com/en-us/dotnet/co...)