Шутка: Имитируйте метод модуля NPM

#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