Как мне издеваться над методом издеваемого модуля с помощью Jest?

#typescript #jestjs #electron

#typescript #jestjs #электрон

Вопрос:

Я пытаюсь издеваться над «диалогом» в модуле electron, используя jest, и сталкиваюсь с проблемами ниже. При настройке макета непосредственно на объекте он работает (случай 1). Однако при сохранении макетной функции в переменной и установке ее в макетном объекте происходит сбой (случай 2). Любой ввод, почему это так? Я новичок в jest и js в целом. Однако я подумал, что эти два случая должны вести себя одинаково.

Случай 1: работа

 jest.mock('electron', () => ({
  dialog: {
    showOpenDialog: jest.fn(()=>({filePaths:['']})),
  },
}));
 

Случай 2: не работает. Ошибка: ошибка типа: electron_1.dialog.showOpenDialog не является функцией

 const showOpenDialogMock = jest.fn(()=>({filePaths:['']}));
jest.mock('electron', () => ({
  dialog: {
    showOpenDialog: showOpenDialogMock,
  },
}));
 

Тест:

 test("Menu click", async () => {   

    const setDirMenuItem = subMenu.getSetProjectDirSubMenu(
      <any>mainWindow,
      <any>projectSettings
    );
    await setDirMenuItem.click();
    expect(showOpenDialogMock).toHaveBeenCalledTimes(1);
  }
  );
 

Код в тесте:

 export const getSetProjectDirSubMenu = (
  mainWindow: BrowserWindow,
  projectSettings: ProjectSettings
) => ({
  label: 'Set Project Directory',
  click: async () => {
    const result = await dialog.showOpenDialog(mainWindow, {
      properties: ['openDirectory'],
      defaultPath: projectSettings.getProjectDir()
    });

    if (result.filePaths[0]) {
      projectSettings.setProjectDir(result.filePaths[0]);
      mainWindow.webContents.send('PROJECT_DIRECTORY_SET', {});
    }
  }
});

 

Заранее спасибо.

Ответ №1:

jest.mock вызовы перемещаются в начало файла (поднимаются). Итак, в случае 2 макет создается до const showOpenDialogMock определения.

Код, который на самом деле выполняется, больше похож на:

 jest.mock('electron', () => ({
  dialog: {
    showOpenDialog: showOpenDialogMock,
  },
}));
const showOpenDialogMock = jest.fn(()=>({filePaths:['']}));
 

Зная это, вот что вы можете попробовать вместо этого:

 import {dialog} from 'electron';

jest.mock('electron', () => ({
  dialog: {
    showOpenDialog: jest.fn(()=>({filePaths:['']})),
  },
}));

test("Menu click", async () => {   
  const setDirMenuItem = subMenu.getSetProjectDirSubMenu(
    <any>mainWindow,
    <any>projectSettings
  );
  await setDirMenuItem.click();
  // note: dialog.showOpenDialog
  expect(dialog.showOpenDialog).toHaveBeenCalledTimes(1);
});
 

Подробнее о функциях модуля и издевательских модулях из документации Jest.