DEV Community

Discussion on: Comparing jest.mock and Dependency Injection in TypeScript

Collapse
 
komanton profile image
Anton Komarov • Edited

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