Как мне заглушить обратный вызов метода модуля с помощью sinon?

Я использую модуль mv для перемещения файлов, более старый модуль, который все еще получает много загрузок и был полезен при перемещении файлов между томами докеров, а также за пределами докеров. Я создал метод для обработки метода mv как обещания.

При модульном тестировании я изо всех сил пытаюсь имитировать mv при использовании в методе.

import mv from 'mv';

export class CmdUtils {
  /**
   * Move a file to a new location. Using mv, this will attempt a mv command, however
   * this could fail with docker volumes and will fallback to the mv module streaming
   * data to the new location as needed.
   * @param filePath - Full path to file
   * @param destinationFilePath - Full path to file's new destination
   */
  public static moveFile = (filePath: string, destinationFilePath: string): Promise<void> => {
    return new Promise((resolve, reject) => {
      mv(filePath, destinationFilePath, err => {
        if (!err) {
          resolve();
        } else {
          console.error('moveFile err', err);
          reject(err);
        }
      });
    });
  }
}

Вот стартовый тест с пробелами:

import mv from 'mv';
import { CmdUtils } from './cmd-utils';

describe("CmdUtils: moveFile", () => {
  it("should successfully move a file using mv module", async () => {
    const sandbox = sinon.createSandbox();
    try {
      const moveFromPath = '/full/path/to/file.jpg';
      const moveToPath = '/full/path/to/destination/file.jpg';

      // Starting attempt at a replacement callback
      const mvCallback = (err: Error) => {
        if (!err) {
          Promise.resolve();
        } else {
          console.error('moveFile err', err.message);
          Promise.reject(err);
        }
      }

      // Stub mv
      sandbox.stub(mv)
      // What am I missing here?

      // Move file
      await CmdUtils.moveFile(moveFromPath, moveToPath);

      // expect no errors... (will revisit this)
    } finally {
      sandbox.restore();
    }
  });
});

Как имитировать успешное перемещение файла? Я вижу похожие вопросы, но пока не нахожу ответа.


person Christopher Stevens    schedule 10.04.2020    source источник
comment
Способ настройки moveFile не позволяет заглушить cb на mv. Вы не передаете обратный вызов в качестве аргумента, поэтому не можете заглушить его для использования в mv. Кажется, вам нужно будет переделать moveFile, чтобы получить доступ к обратному вызову и передать его mv для выполнения.   -  person Andrew Nolan    schedule 10.04.2020
comment
Спасибо за отзыв @AndrewNolan. По мере того, как кофе поглощается, я думаю, что реальный вопрос заключается в том, как выполнить модульное тестирование метода, содержащего mv? Меня не так беспокоит то, что делает mv, а только то, что метод moveFile () ведет себя должным образом. Сообщите мне, имеет ли это смысл, когда я буду расширять возможности модульного тестирования.   -  person Christopher Stevens    schedule 10.04.2020
comment
Мой кофе только сейчас начинает действовать: D. Чтобы получить заглушку, извлеките обратный вызов, который вы применяете к mv, и передайте его как именованный параметр moveFile. Затем этот именованный параметр передается как обратный вызов mv. Затем вы можете проверить, работает ли обратный вызов с помощью resolve или reject. Я сейчас напечатаю ответ.   -  person Andrew Nolan    schedule 10.04.2020
comment
Копировать. Мне интересно, однако, в целях функциональности, должен ли я передать именованный параметр, чтобы заставить работать модульные тесты, например. moveFile('orig.jpg', 'new.jpg', someCallbackIDontCareAbout). Единственное, что меня беспокоит при использовании moveFile (), - это успешное перемещение файла в качестве обещания.   -  person Christopher Stevens    schedule 10.04.2020


Ответы (1)


class CmdUtil {
  static moveFileCb(resolve, reject, err) {
    if (!err) {
      resolve('RESOLVED');
    } else {
      reject(err);
    }
  }

  static moveFile() {
    return new Promise((resolve, reject) => {
      mv('test', 'test', CmdUtil.moveFileCb.bind(this, resolve, reject))
    })
  }
}

тогда тест может быть чем-то похожим на то, что у вас есть, где вы сейчас вставляете moveFileCb. С помощью этой заглушки вы можете проверить / подтвердить, с чем был вызван обратный вызов, сколько раз он был вызван и т. Д.

Боковое примечание: я не писал тест с использованием bind. Это может помешать решению проблемы.

person Andrew Nolan    schedule 10.04.2020
comment
Спасибо за ответ. Я прослежу / попробую это сделать в следующий перерыв. - person Christopher Stevens; 10.04.2020
comment
В конце концов, я использовал встроенную функцию promisify для уменьшения количества строк и исключил ее из тестов, поскольку у меня было более 90% покрытия, охватывающее вещи, над которыми я имел больший контроль, включая методы, которые использовали этот метод (они могли обрабатывать ошибки). - person Christopher Stevens; 18.04.2020