Я сделал библиотеку перехватчиков React, доступную на NPM.
Для модульного тестирования этой библиотеки я использую JEST с Typescript.
Он имеет зависимость с другим модулем узла @brand/dependencyModule
.
Этот @brand/dependencyModule
выполняет HTTP-запрос и генерирует события (с { EventEmitter } from 'events'
), которые мне нужно имитировать.
Я пытался следовать документации JEST , чтобы вручную смоделировать эту библиотеку.
Во-первых, позвольте мне показать вам, что я пробовал:
- Создать папку
__mocks__
на уровне проекта root (на том же уровне, что и node_modules
) - Создать подпапку
@brand
внутри __mocks__
- Создать файл TS
dependencyModule.ts
внутри @brand
папку
Внутри __mocks__/@brand/dependencyModule.ts
, у нас есть:
'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);
}
}));
Теперь в моем файле src/**/index.test.ts
у меня есть:
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);
});
});
Наконец, давайте посмотрим на файл MyHookProvider.tsx
, в котором используется '@ 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
},
};
Теперь ошибка, возникающая при запуске npm run test
, я ожидаю, что шутка обнаружит, что я издевался над @brand/dependencyModule
, но когда я отлаживаю, он фактически запускает настоящую библиотеку. Я не знаю, чего мне не хватает, чтобы это работало.
Есть помощь? Спасибо!
Вот библиотеки, которые я использую для модульного тестирования:
"@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 как это:
"jest": {
"setupFilesAfterEnv": [
"./src/setupTests.js"
]
}
with src/setupTests.js
:
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });