#typescript #unit-testing #jestjs #mocking
Вопрос:
Мне нужно протестировать функцию, в которой я вызываю другую функцию из пакета NPM под названием «сердцебиения»:
индекс.ts
export async function checkUp(app: App, heart, beats: number, iterations: number): Promise<void> {
// const heart = heartbeats.createHeart(1000, 'checkUp');
heart.createEvent(beats, { countTo: iterations }, async (count, last) => {
const secondCheck = await secondCheckStatus();
if (!secondCheck) {
app.quit();
}
});
}
индекс.тест.ts
import * as Heartbeats from 'heartbeats';
import { secondCheckStatus } from './utils';
...
jest.mock('./utils', () => ({
...jest.requireActual('./utils'),
secondCheckStatus: jest.fn(),
}));
const mockSecondCheckStatus = secondCheckStatus as jest.MockedFunction< typeof secondCheckStatus >;
...
beforeEach(() => {
jest.clearAllMocks();
});
...
it('should auto kill app after checks', async () => {
const mockApp = new MockApp() as unknown as jest.Mocked<App>;
const mockHeart = Heartbeats.heart as unknown as jest.Mock;
const mockCreateEvent = Heartbeats.heart.createEvent as unknown as jest.MockedFunction<
typeof Heartbeats.heart.createEvent
>;
mockCreateEvent.mockImplementation((beats, iter, cb) => {
cb(null, null);
});
mockSecondCheckStatus.mockResolvedValueOnce(false);
mockApp.requestSingleInstanceLock.mockReturnValue(true);
const isRunning = await checkUp(mockApp, mockHeart, 1, 1);
await main(mockApp);
expect(mockApp.quit).toHaveBeenCalledTimes(1);
expect(isRunning).toBe(false);
});
Но я всегда получаю:
Ошибка типа: Не удается прочитать свойство «Макет реализации» неопределенного
83 | typeof Heartbeats.heart.createEvent
84 | >;
> 85 | mockCreateEvent.mockImplementation((beats, iter, cb) => {
Есть идеи, что я делаю не так?
Большое спасибо (все еще долгий путь для меня, чтобы работать гладко с Шуткой)
Комментарии:
1. Откуда это
secondCheckStatus
берется?2. Я отредактировал тестовый файл со
secondCheckStatus
ссылкой3. Я добавил
const mockSecondCheckStatus = secondCheckStatus as jest.MockedFunction< typeof secondCheckStatus >;
в тестовый файл, я забыл его.
Ответ №1:
Поскольку checkUp
функция принимает app
и heart
в качестве своих параметров, вы можете создавать макетные объекты, соответствующие этим типам параметров или интерфейсам.
Только secondCheckStatus
функция импортируется по import
ключевому слову, вы должны использовать jest.mock()
метод, чтобы издеваться над ней.
Для обработки проблемы типа TS для издевательского объекта/функции вы можете использовать вспомогательную функцию издевательства(item: T, deep = false) ts-jest
.
Напр.
index.ts
:
import { secondCheckStatus } from './utils';
export async function checkUp(app, heart, beats: number, iterations: number): Promise<void> {
heart.createEvent(beats, { countTo: iterations }, async (count, last) => {
const secondCheck = await secondCheckStatus();
if (!secondCheck) {
app.quit();
}
});
}
util.ts
:
export async function secondCheckStatus() {
return true;
}
index.test.ts
:
import { checkUp } from './';
import { secondCheckStatus } from './utils';
import { mocked } from 'ts-jest/utils';
jest.mock('./utils', () => ({
...(jest.requireActual('./utils') as object),
secondCheckStatus: jest.fn(),
}));
const mockSecondCheckStatus = mocked(secondCheckStatus);
describe('69720608', () => {
beforeEach(() => {
jest.clearAllMocks();
});
test('should pass', async () => {
const mockApp = {
quit: jest.fn(),
};
const mockHeart = {
createEvent: jest.fn().mockImplementation(async (beats, options, callback) => {
await callback();
}),
};
await checkUp(mockApp, mockHeart, 1, 1);
expect(mockSecondCheckStatus).toBeCalledTimes(1);
expect(mockApp.quit).toBeCalledTimes(1);
});
});
результат теста:
PASS examples/69720608/index.test.ts (13.424 s)
69720608
✓ should pass (4 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 88.89 | 50 | 75 | 87.5 |
index.ts | 100 | 50 | 100 | 100 | 6
utils.ts | 50 | 100 | 0 | 50 | 2
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 15.478 s