I made a React hooks library, available on NPM.
For unit testing this lib, I'm using JEST with Typescript.
It has a dependency with another node module @brand/dependencyModule.
This @brand/dependencyModule is doing http request and emits events (with { EventEmitter } from 'events') which I need to mock.
I tried to follow the JEST documentation to do manual mock of this lib.
First, let me show you what I tried:
- Create
__mocks__folder at project root level (same level asnode_modules) - Create subfolder
@brandinside__mocks__ - Create TS file
dependencyModule.tsinside@brandfolder
Inside __mocks__/@brand/dependencyModule.ts, we have:
'use strict';
import { EventEmitter } from 'events';
import {
SomeTyping
} from '@brand/dependencyModule';
class MockVisitor extends EventEmitter {
someAttribute1: string;
someAttribute2: string;
someAttribute3: SomeTyping;
constructor(some) {
super();
this.someAttribute1 = some;
this.someAttribute2 = parameter;
this.someAttribute3 = mockHttpResponse;
setTimeout(() => {
this.emit('ready');
}, 100);
}
}
class MockModule {
otherAttribute1: string;
constructor(otherParam) {
this.otherAttribute1 = otherParam;
}
public newVisitor(some, param) {
return new MockVisitor(some, param);
}
}
export default jest.fn().mockImplementation(() => ({
start: (someStuff) => {
return new MockModule(someStuff);
}
}));
Now, in my src/**/index.test.ts file, I have:
describe('trying to mock @brand/dependencyModule', () => {
test('it should use the mock version', async () => {
let isReady = null;
const { container } = render(
<MyHookProvider
onInitDone={() => {
isReady = true;
}}
>
<div>Hello</div>
</MyHookProvider>
);
await waitFor(() => {
if (!isReady) {
throw new Error('not ready');
}
});
expect(isReady).toEqual(true);
});
});
Finaly, let's have a look to MyHookProvider.tsx file which uses '@brand/dependencyModule':
import React, { useState, useEffect, SetStateAction, Dispatch, useContext } from 'react';
import dependencyModule from '@brand/dependencyModule';
export const MyHookProvider: React.SFC</*...*/> = ({
// ...
onInitDone,
}: ProviderProps) => {
useEffect(() => {
const module = dependencyModule.start('hello');
const visitorInstance = module.newVisitor('stack','overflow');
visitorInstance.on('ready', () => {
onInitDone()
});
}, [/*...*/]);
return (
<MyHook.Provider value={{ ... }}>
{"I'm ready."}
</MyHook.Provider>
);
};
MyHookProvider.defaultProps = {
onInitDone: (): void => {
// do nothing
},
};
Now the error which I have when run npm run test, I expect jest to detect I have mocked @brand/dependencyModule but when I'm debugging, it's actually running the real lib. I don't what I'm missing to make it work.
Any help ? Thank you !
Here the libs which I'm using for unit testing:
"@testing-library/jest-dom": "^5.5.0",
"@types/jest": "^25.2.1",
"@types/enzyme": "^3.10.5",
"@types/enzyme-adapter-react-16": "^1.0.6",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.4.4",
"jest": "^25.4.0",
"jest-mock-axios": "^3.2.0",
"ts-jest": "^25.4.0",
jest config setup like this:
"jest": {
"setupFilesAfterEnv": [
"./src/setupTests.js"
]
}
with src/setupTests.js :
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });